blob: c503083028aed1c91ee4513c83abcbd19c7c17a8 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(uint64_t Features_) :
47 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 uint64_t getFeatures() const { return Features; }
74 void setFeatures(uint64_t Features_) { Features = Features_; }
75
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteinc3434b32015-05-13 10:28:46 +000081 static const uint64_t AllArchRelatedMask =
82 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
83 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
84 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
85 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
86 Mips::FeatureMips32r3 | Mips::FeatureMips32r5 | Mips::FeatureMips32r6 |
87 Mips::FeatureMips64 | Mips::FeatureMips64r2 | Mips::FeatureMips64r3 |
88 Mips::FeatureMips64r5 | Mips::FeatureMips64r6 | Mips::FeatureCnMips |
89 Mips::FeatureFP64Bit | Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
Daniel Sandersf0df2212014-08-04 12:20:00 +000090
Jack Carter0b744b32012-10-04 02:29:46 +000091private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000092 unsigned ATReg;
93 bool Reorder;
94 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000095 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000096};
97}
98
99namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000100class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000101 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000102 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000103 return static_cast<MipsTargetStreamer &>(TS);
104 }
105
Jack Carterb4dbc172012-09-05 23:34:03 +0000106 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000107 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000108 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000109 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
110 // nullptr, which indicates that no function is currently
111 // selected. This usually happens after an '.end func'
112 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000113
Daniel Sandersef638fe2014-10-03 15:37:37 +0000114 // Print a warning along with its fix-it message at the given range.
115 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
116 SMRange Range, bool ShowColors = true);
117
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000118#define GET_ASSEMBLER_HEADER
119#include "MipsGenAsmMatcher.inc"
120
Matheus Almeida595fcab2014-06-11 15:05:56 +0000121 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
122
Chad Rosier49963552012-10-13 00:26:04 +0000123 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000124 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000125 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000126 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000127
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000128 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
Toma Tabacu13964452014-09-04 13:23:44 +0000131 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132
Toma Tabacu13964452014-09-04 13:23:44 +0000133 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000134
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
136 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
David Blaikie960ea3f2014-06-08 16:18:35 +0000140 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000141
142 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000143 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
Jack Carter873c7242013-01-12 01:03:14 +0000146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000148
Toma Tabacu13964452014-09-04 13:23:44 +0000149 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000150
Toma Tabacu13964452014-09-04 13:23:44 +0000151 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000154
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000158
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000159 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000160 parseRegisterPair (OperandVector &Operands);
161
162 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000163 parseMovePRegPair(OperandVector &Operands);
164
165 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166 parseRegisterList (OperandVector &Operands);
167
David Blaikie960ea3f2014-06-08 16:18:35 +0000168 bool searchSymbolAlias(OperandVector &Operands);
169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000171
Jack Carter30a59822012-10-04 04:03:53 +0000172 bool needsExpansion(MCInst &Inst);
173
Matheus Almeida3813d572014-06-19 14:39:14 +0000174 // Expands assembly pseudo instructions.
175 // Returns false on success, true otherwise.
176 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000177 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000178
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000179 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
181
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000182 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
183 bool Is32BitImm, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
185
Toma Tabacu00e98672015-05-01 12:19:27 +0000186 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000187 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000188
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000189 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000190 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000191
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000192 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000193 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000194 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
195 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000196
Toma Tabacub5592ee2015-05-14 10:02:58 +0000197 void expandLoadAddressSym(const MCOperand &DstRegOp, const MCOperand &SymOp,
Toma Tabacuec1de822015-05-14 10:53:40 +0000198 bool Is32BitSym, SMLoc IDLoc,
199 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +0000200
Jack Carter9e65aa32013-03-22 00:05:30 +0000201 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
203 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000204
205 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Toma Tabacu234482a2015-03-16 12:03:39 +0000208 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000211 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
212 SmallVectorImpl<MCInst> &Instructions);
213
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000214 bool reportParseError(Twine ErrorMsg);
215 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000216
Jack Carterb5cf5902013-04-17 00:18:04 +0000217 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000218 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000219
Vladimir Medic4c299852013-11-06 11:27:05 +0000220 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000221
222 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000223 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000224 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000225 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000226 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000227 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000228 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000229 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000230 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000231 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000232
233 bool parseSetAtDirective();
234 bool parseSetNoAtDirective();
235 bool parseSetMacroDirective();
236 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000237 bool parseSetMsaDirective();
238 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000239 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000240 bool parseSetReorderDirective();
241 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000242 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000243 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000244 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000245 bool parseSetPopDirective();
246 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000247
Jack Carterd76b2372013-03-21 21:44:16 +0000248 bool parseSetAssignment();
249
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000250 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000251 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000252 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000253 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000254 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000255 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
256 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000257
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000258 bool parseInternalDirectiveReallowModule();
259
Jack Carterdc1e35d2012-09-06 20:00:02 +0000260 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000261
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000262 bool eatComma(StringRef ErrorStr);
263
Jack Carter1ac53222013-02-20 23:11:17 +0000264 int matchCPURegisterName(StringRef Symbol);
265
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000266 int matchHWRegsRegisterName(StringRef Symbol);
267
Jack Carter873c7242013-01-12 01:03:14 +0000268 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000269
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000270 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000271
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000272 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000273
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000274 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000275
Jack Carter5dc8ac92013-09-25 23:50:44 +0000276 int matchMSA128RegisterName(StringRef Name);
277
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000278 int matchMSA128CtrlRegisterName(StringRef Name);
279
Jack Carterd0bd6422013-04-18 00:41:53 +0000280 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000281
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000282 unsigned getGPR(int RegNo);
283
Toma Tabacu89a712b2015-04-15 10:48:56 +0000284 /// Returns the internal register number for the current AT. Also checks if
285 /// the current AT is unavailable (set to $0) and gives an error if it is.
286 /// This should be used in pseudo-instruction expansions which need AT.
287 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000288
289 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000290 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000291
292 // Helper function that checks if the value of a vector index is within the
293 // boundaries of accepted values for each RegisterKind
294 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
295 bool validateMSAIndex(int Val, int RegKind);
296
Daniel Sandersf0df2212014-08-04 12:20:00 +0000297 // Selects a new architecture by updating the FeatureBits with the necessary
298 // info including implied dependencies.
299 // Internally, it clears all the feature bits related to *any* architecture
300 // and selects the new one using the ToggleFeature functionality of the
301 // MCSubtargetInfo object that handles implied dependencies. The reason we
302 // clear all the arch related bits manually is because ToggleFeature only
303 // clears the features that imply the feature being cleared and not the
304 // features implied by the feature being cleared. This is easier to see
305 // with an example:
306 // --------------------------------------------------
307 // | Feature | Implies |
308 // | -------------------------------------------------|
309 // | FeatureMips1 | None |
310 // | FeatureMips2 | FeatureMips1 |
311 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
312 // | FeatureMips4 | FeatureMips3 |
313 // | ... | |
314 // --------------------------------------------------
315 //
316 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
317 // FeatureMipsGP64 | FeatureMips1)
318 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
319 void selectArch(StringRef ArchFeature) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000320 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000321 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
322 STI.setFeatureBits(FeatureBits);
323 setAvailableFeatures(
324 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000325 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000326 }
327
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000328 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000329 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000330 setAvailableFeatures(
331 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000332 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000333 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000334 }
335
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000336 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000337 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000338 setAvailableFeatures(
339 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000340 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000341 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000342 }
343
Rafael Espindola870c4e92012-01-11 03:56:41 +0000344public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000345 enum MipsMatchResultTy {
346 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
347#define GET_OPERAND_DIAGNOSTIC_TYPES
348#include "MipsGenAsmMatcher.inc"
349#undef GET_OPERAND_DIAGNOSTIC_TYPES
350
351 };
352
Joey Gouly0e76fa72013-09-12 10:28:05 +0000353 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000354 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000355 : MCTargetAsmParser(), STI(sti),
356 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
357 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000358 MCAsmParserExtension::Initialize(parser);
359
Toma Tabacu11e14a92015-04-21 11:50:52 +0000360 parser.addAliasForDirective(".asciiz", ".asciz");
361
Jack Carterb4dbc172012-09-05 23:34:03 +0000362 // Initialize the set of available features.
363 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000364
365 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000366 AssemblerOptions.push_back(
367 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000368
369 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000370 AssemblerOptions.push_back(
371 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000372
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000373 getTargetStreamer().updateABIInfo(*this);
374
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000375 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000376 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000377
378 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000379 }
380
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000381 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
382 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
383
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000384 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
385 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000386 const MipsABIInfo &getABI() const { return ABI; }
387 bool isABI_N32() const { return ABI.IsN32(); }
388 bool isABI_N64() const { return ABI.IsN64(); }
389 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000390 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000391
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000392 bool useOddSPReg() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000393 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000394 }
395
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000396 bool inMicroMipsMode() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000397 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000398 }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000399 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
400 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
401 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
402 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
403 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 bool hasMips32() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000405 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000406 }
407 bool hasMips64() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000408 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000409 }
410 bool hasMips32r2() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000411 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 }
413 bool hasMips64r2() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000414 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000415 }
Daniel Sanders17793142015-02-18 16:24:50 +0000416 bool hasMips32r3() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000417 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000418 }
419 bool hasMips64r3() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000420 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000421 }
422 bool hasMips32r5() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000423 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000424 }
425 bool hasMips64r5() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000426 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000427 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000428 bool hasMips32r6() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000429 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000430 }
431 bool hasMips64r6() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000432 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433 }
Kai Nackee0245392015-01-27 19:11:28 +0000434 bool hasCnMips() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000435 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000436 }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000437 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
438 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
439 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440
441 bool inMips16Mode() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000442 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000443 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000444
Eric Christophere8ae3e32015-05-07 23:10:21 +0000445 bool useSoftFloat() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000446 return (STI.getFeatureBits() & Mips::FeatureSoftFloat);
Toma Tabacu506cfd02015-05-07 10:29:52 +0000447 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000448
Toma Tabacud9d344b2015-04-27 14:05:04 +0000449 /// Warn if RegIndex is the same as the current AT.
450 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000451};
452}
453
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000454namespace {
455
456/// MipsOperand - Instances of this class represent a parsed Mips machine
457/// instruction.
458class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000459public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000460 /// Broad categories of register classes
461 /// The exact class is finalized by the render method.
462 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000463 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000464 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 RegKind_FCC = 4, /// FCC
467 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
468 RegKind_MSACtrl = 16, /// MSA control registers
469 RegKind_COP2 = 32, /// COP2
470 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
471 /// context).
472 RegKind_CCR = 128, /// CCR
473 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000474 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000475
476 /// Potentially any (e.g. $1)
477 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
478 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000479 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000480 };
481
482private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000483 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000484 k_Immediate, /// An immediate (possibly involving symbol references)
485 k_Memory, /// Base + Offset Memory Address
486 k_PhysRegister, /// A physical register from the Mips namespace
487 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000488 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000489 k_RegList, /// A physical register list
490 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000491 } Kind;
492
David Blaikie960ea3f2014-06-08 16:18:35 +0000493public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000494 MipsOperand(KindTy K, MipsAsmParser &Parser)
495 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
496
David Blaikie960ea3f2014-06-08 16:18:35 +0000497private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000498 /// For diagnostics, and checking the assembler temporary
499 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000500
Eric Christopher8996c5d2013-03-15 00:42:55 +0000501 struct Token {
502 const char *Data;
503 unsigned Length;
504 };
505
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000506 struct PhysRegOp {
507 unsigned Num; /// Register Number
508 };
509
510 struct RegIdxOp {
511 unsigned Index; /// Index into the register class
512 RegKind Kind; /// Bitfield of the kinds it could possibly be
513 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000514 };
515
516 struct ImmOp {
517 const MCExpr *Val;
518 };
519
520 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000522 const MCExpr *Off;
523 };
524
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000525 struct RegListOp {
526 SmallVector<unsigned, 10> *List;
527 };
528
Jack Carterb4dbc172012-09-05 23:34:03 +0000529 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000530 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000531 struct PhysRegOp PhysReg;
532 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000533 struct ImmOp Imm;
534 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000535 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000536 };
537
538 SMLoc StartLoc, EndLoc;
539
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000540 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000541 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
542 const MCRegisterInfo *RegInfo,
543 SMLoc S, SMLoc E,
544 MipsAsmParser &Parser) {
545 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000546 Op->RegIdx.Index = Index;
547 Op->RegIdx.RegInfo = RegInfo;
548 Op->RegIdx.Kind = RegKind;
549 Op->StartLoc = S;
550 Op->EndLoc = E;
551 return Op;
552 }
553
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000554public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000555 /// Coerce the register to GPR32 and return the real register for the current
556 /// target.
557 unsigned getGPR32Reg() const {
558 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000559 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 unsigned ClassID = Mips::GPR32RegClassID;
561 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000562 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000563
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000564 /// Coerce the register to GPR32 and return the real register for the current
565 /// target.
566 unsigned getGPRMM16Reg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
568 unsigned ClassID = Mips::GPR32RegClassID;
569 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
570 }
571
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000572 /// Coerce the register to GPR64 and return the real register for the current
573 /// target.
574 unsigned getGPR64Reg() const {
575 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
576 unsigned ClassID = Mips::GPR64RegClassID;
577 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000578 }
579
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000580private:
581 /// Coerce the register to AFGR64 and return the real register for the current
582 /// target.
583 unsigned getAFGR64Reg() const {
584 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
585 if (RegIdx.Index % 2 != 0)
586 AsmParser.Warning(StartLoc, "Float register should be even.");
587 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
588 .getRegister(RegIdx.Index / 2);
589 }
590
591 /// Coerce the register to FGR64 and return the real register for the current
592 /// target.
593 unsigned getFGR64Reg() const {
594 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
595 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
596 .getRegister(RegIdx.Index);
597 }
598
599 /// Coerce the register to FGR32 and return the real register for the current
600 /// target.
601 unsigned getFGR32Reg() const {
602 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
603 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
604 .getRegister(RegIdx.Index);
605 }
606
607 /// Coerce the register to FGRH32 and return the real register for the current
608 /// target.
609 unsigned getFGRH32Reg() const {
610 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
611 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
612 .getRegister(RegIdx.Index);
613 }
614
615 /// Coerce the register to FCC and return the real register for the current
616 /// target.
617 unsigned getFCCReg() const {
618 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
619 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
620 .getRegister(RegIdx.Index);
621 }
622
623 /// Coerce the register to MSA128 and return the real register for the current
624 /// target.
625 unsigned getMSA128Reg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
627 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
628 // identical
629 unsigned ClassID = Mips::MSA128BRegClassID;
630 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
631 }
632
633 /// Coerce the register to MSACtrl and return the real register for the
634 /// current target.
635 unsigned getMSACtrlReg() const {
636 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
637 unsigned ClassID = Mips::MSACtrlRegClassID;
638 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
639 }
640
641 /// Coerce the register to COP2 and return the real register for the
642 /// current target.
643 unsigned getCOP2Reg() const {
644 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
645 unsigned ClassID = Mips::COP2RegClassID;
646 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
647 }
648
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000649 /// Coerce the register to COP3 and return the real register for the
650 /// current target.
651 unsigned getCOP3Reg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
653 unsigned ClassID = Mips::COP3RegClassID;
654 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
655 }
656
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000657 /// Coerce the register to ACC64DSP and return the real register for the
658 /// current target.
659 unsigned getACC64DSPReg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
661 unsigned ClassID = Mips::ACC64DSPRegClassID;
662 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to HI32DSP and return the real register for the
666 /// current target.
667 unsigned getHI32DSPReg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
669 unsigned ClassID = Mips::HI32DSPRegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
671 }
672
673 /// Coerce the register to LO32DSP and return the real register for the
674 /// current target.
675 unsigned getLO32DSPReg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
677 unsigned ClassID = Mips::LO32DSPRegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
679 }
680
681 /// Coerce the register to CCR and return the real register for the
682 /// current target.
683 unsigned getCCRReg() const {
684 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
685 unsigned ClassID = Mips::CCRRegClassID;
686 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
687 }
688
689 /// Coerce the register to HWRegs and return the real register for the
690 /// current target.
691 unsigned getHWRegsReg() const {
692 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
693 unsigned ClassID = Mips::HWRegsRegClassID;
694 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
695 }
696
697public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000698 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000699 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000700 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000701 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000702 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000703 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000704 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000705 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000706 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000707
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000708 void addRegOperands(MCInst &Inst, unsigned N) const {
709 llvm_unreachable("Use a custom parser instead");
710 }
711
Daniel Sanders21bce302014-04-01 12:35:23 +0000712 /// Render the operand to an MCInst as a GPR32
713 /// Asserts if the wrong number of operands are requested, or the operand
714 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000717 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000718 }
719
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000720 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
721 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000722 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000723 }
724
Jozef Kolek1904fa22014-11-24 14:25:53 +0000725 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
726 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000727 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000728 }
729
Zoran Jovanovic41688672015-02-10 16:36:20 +0000730 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
731 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000732 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000733 }
734
Daniel Sanders21bce302014-04-01 12:35:23 +0000735 /// Render the operand to an MCInst as a GPR64
736 /// Asserts if the wrong number of operands are requested, or the operand
737 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
739 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000740 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 }
742
743 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
744 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000745 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000746 }
747
748 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
749 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000750 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 }
752
753 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
754 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000755 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000756 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000757 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000758 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
759 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 }
761
762 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
763 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000764 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 }
766
767 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
768 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000769 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000770 }
771
772 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
773 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000774 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 }
776
777 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
778 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000779 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 }
781
782 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
783 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000784 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 }
786
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000787 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
788 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000789 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000790 }
791
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
793 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000794 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000795 }
796
797 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
798 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000799 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 }
801
802 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
803 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000804 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 }
806
807 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
808 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000809 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 }
811
812 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
813 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 }
816
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000817 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000818 assert(N == 1 && "Invalid number of operands!");
819 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000820 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000821 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000822
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000823 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000824 assert(N == 2 && "Invalid number of operands!");
825
Jim Grosbache9119e42015-05-13 18:37:00 +0000826 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000827
828 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000829 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000830 }
831
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000832 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 2 && "Invalid number of operands!");
834
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000836
837 const MCExpr *Expr = getMemOff();
838 addExpr(Inst, Expr);
839 }
840
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000841 void addRegListOperands(MCInst &Inst, unsigned N) const {
842 assert(N == 1 && "Invalid number of operands!");
843
844 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000846 }
847
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000848 void addRegPairOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 2 && "Invalid number of operands!");
850 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000851 Inst.addOperand(MCOperand::createReg(RegNo++));
852 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000853 }
854
Zoran Jovanovic41688672015-02-10 16:36:20 +0000855 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 2 && "Invalid number of operands!");
857 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000858 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000859 }
860
Craig Topper56c590a2014-04-29 07:58:02 +0000861 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000862 // As a special case until we sort out the definition of div/divu, pretend
863 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
864 if (isGPRAsmReg() && RegIdx.Index == 0)
865 return true;
866
867 return Kind == k_PhysRegister;
868 }
869 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000870 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 bool isConstantImm() const {
872 return isImm() && dyn_cast<MCConstantExpr>(getImm());
873 }
Craig Topper56c590a2014-04-29 07:58:02 +0000874 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 // Note: It's not possible to pretend that other operand kinds are tokens.
876 // The matcher emitter checks tokens first.
877 return Kind == k_Token;
878 }
Craig Topper56c590a2014-04-29 07:58:02 +0000879 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000880 bool isConstantMemOff() const {
881 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
882 }
883 template <unsigned Bits> bool isMemWithSimmOffset() const {
884 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
885 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000886 bool isMemWithGRPMM16Base() const {
887 return isMem() && getMemBase()->isMM16AsmReg();
888 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000889 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
890 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
891 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
892 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000893 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
894 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
895 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
896 && (getMemBase()->getGPR32Reg() == Mips::SP);
897 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000898 bool isRegList16() const {
899 if (!isRegList())
900 return false;
901
902 int Size = RegList.List->size();
903 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
904 RegList.List->back() != Mips::RA)
905 return false;
906
907 int PrevReg = *RegList.List->begin();
908 for (int i = 1; i < Size - 1; i++) {
909 int Reg = (*(RegList.List))[i];
910 if ( Reg != PrevReg + 1)
911 return false;
912 PrevReg = Reg;
913 }
914
915 return true;
916 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000917 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 bool isLSAImm() const {
919 if (!isConstantImm())
920 return false;
921 int64_t Val = getConstantImm();
922 return 1 <= Val && Val <= 4;
923 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000924 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000925 bool isMovePRegPair() const {
926 if (Kind != k_RegList || RegList.List->size() != 2)
927 return false;
928
929 unsigned R0 = RegList.List->front();
930 unsigned R1 = RegList.List->back();
931
932 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
933 (R0 == Mips::A1 && R1 == Mips::A3) ||
934 (R0 == Mips::A2 && R1 == Mips::A3) ||
935 (R0 == Mips::A0 && R1 == Mips::S5) ||
936 (R0 == Mips::A0 && R1 == Mips::S6) ||
937 (R0 == Mips::A0 && R1 == Mips::A1) ||
938 (R0 == Mips::A0 && R1 == Mips::A2) ||
939 (R0 == Mips::A0 && R1 == Mips::A3))
940 return true;
941
942 return false;
943 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000944
945 StringRef getToken() const {
946 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000947 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000948 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000949 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000950
Craig Topper56c590a2014-04-29 07:58:02 +0000951 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 // As a special case until we sort out the definition of div/divu, pretend
953 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
954 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
955 RegIdx.Kind & RegKind_GPR)
956 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000957
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000958 assert(Kind == k_PhysRegister && "Invalid access!");
959 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000960 }
961
Jack Carterb4dbc172012-09-05 23:34:03 +0000962 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000963 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 return Imm.Val;
965 }
966
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000967 int64_t getConstantImm() const {
968 const MCExpr *Val = getImm();
969 return static_cast<const MCConstantExpr *>(Val)->getValue();
970 }
971
972 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000973 assert((Kind == k_Memory) && "Invalid access!");
974 return Mem.Base;
975 }
976
977 const MCExpr *getMemOff() const {
978 assert((Kind == k_Memory) && "Invalid access!");
979 return Mem.Off;
980 }
981
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000982 int64_t getConstantMemOff() const {
983 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
984 }
985
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000986 const SmallVectorImpl<unsigned> &getRegList() const {
987 assert((Kind == k_RegList) && "Invalid access!");
988 return *(RegList.List);
989 }
990
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000991 unsigned getRegPair() const {
992 assert((Kind == k_RegPair) && "Invalid access!");
993 return RegIdx.Index;
994 }
995
David Blaikie960ea3f2014-06-08 16:18:35 +0000996 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
997 MipsAsmParser &Parser) {
998 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000999 Op->Tok.Data = Str.data();
1000 Op->Tok.Length = Str.size();
1001 Op->StartLoc = S;
1002 Op->EndLoc = S;
1003 return Op;
1004 }
1005
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 /// Create a numeric register (e.g. $1). The exact register remains
1007 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001008 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001009 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001010 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001011 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001013 }
1014
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 /// Create a register that is definitely a GPR.
1016 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001017 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001018 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001019 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001021 }
1022
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 /// Create a register that is definitely a FGR.
1024 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001025 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001026 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001027 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001028 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1029 }
1030
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001031 /// Create a register that is definitely a HWReg.
1032 /// This is typically only used for named registers such as $hwr_cpunum.
1033 static std::unique_ptr<MipsOperand>
1034 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1035 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1036 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1037 }
1038
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001039 /// Create a register that is definitely an FCC.
1040 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001041 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001042 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001043 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001044 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1045 }
1046
1047 /// Create a register that is definitely an ACC.
1048 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001049 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001050 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001051 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1053 }
1054
1055 /// Create a register that is definitely an MSA128.
1056 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001057 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001058 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001059 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1061 }
1062
1063 /// Create a register that is definitely an MSACtrl.
1064 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001065 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001066 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001067 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1069 }
1070
David Blaikie960ea3f2014-06-08 16:18:35 +00001071 static std::unique_ptr<MipsOperand>
1072 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1073 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001074 Op->Imm.Val = Val;
1075 Op->StartLoc = S;
1076 Op->EndLoc = E;
1077 return Op;
1078 }
1079
David Blaikie960ea3f2014-06-08 16:18:35 +00001080 static std::unique_ptr<MipsOperand>
1081 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1082 SMLoc E, MipsAsmParser &Parser) {
1083 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1084 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001085 Op->Mem.Off = Off;
1086 Op->StartLoc = S;
1087 Op->EndLoc = E;
1088 return Op;
1089 }
1090
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001091 static std::unique_ptr<MipsOperand>
1092 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1093 MipsAsmParser &Parser) {
1094 assert (Regs.size() > 0 && "Empty list not allowed");
1095
1096 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001097 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001098 Op->StartLoc = StartLoc;
1099 Op->EndLoc = EndLoc;
1100 return Op;
1101 }
1102
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001103 static std::unique_ptr<MipsOperand>
1104 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1105 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1106 Op->RegIdx.Index = RegNo;
1107 Op->StartLoc = S;
1108 Op->EndLoc = E;
1109 return Op;
1110 }
1111
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 bool isGPRAsmReg() const {
1113 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001114 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001115 bool isMM16AsmReg() const {
1116 if (!(isRegIdx() && RegIdx.Kind))
1117 return false;
1118 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1119 || RegIdx.Index == 16 || RegIdx.Index == 17);
1120 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001121 bool isMM16AsmRegZero() const {
1122 if (!(isRegIdx() && RegIdx.Kind))
1123 return false;
1124 return (RegIdx.Index == 0 ||
1125 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1126 RegIdx.Index == 17);
1127 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001128 bool isMM16AsmRegMoveP() const {
1129 if (!(isRegIdx() && RegIdx.Kind))
1130 return false;
1131 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1132 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1133 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 bool isFGRAsmReg() const {
1135 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1136 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001137 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 bool isHWRegsAsmReg() const {
1139 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001140 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 bool isCCRAsmReg() const {
1142 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001143 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001144 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001145 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1146 return false;
1147 if (!AsmParser.hasEightFccRegisters())
1148 return RegIdx.Index == 0;
1149 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001150 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 bool isACCAsmReg() const {
1152 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001153 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001154 bool isCOP2AsmReg() const {
1155 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001156 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001157 bool isCOP3AsmReg() const {
1158 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1159 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001160 bool isMSA128AsmReg() const {
1161 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001162 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001163 bool isMSACtrlAsmReg() const {
1164 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001165 }
1166
Jack Carterb4dbc172012-09-05 23:34:03 +00001167 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001168 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001169 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001170 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001171
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001172 virtual ~MipsOperand() {
1173 switch (Kind) {
1174 case k_Immediate:
1175 break;
1176 case k_Memory:
1177 delete Mem.Base;
1178 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001179 case k_RegList:
1180 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001181 case k_PhysRegister:
1182 case k_RegisterIndex:
1183 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001184 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001185 break;
1186 }
1187 }
1188
Craig Topper56c590a2014-04-29 07:58:02 +00001189 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001190 switch (Kind) {
1191 case k_Immediate:
1192 OS << "Imm<";
1193 Imm.Val->print(OS);
1194 OS << ">";
1195 break;
1196 case k_Memory:
1197 OS << "Mem<";
1198 Mem.Base->print(OS);
1199 OS << ", ";
1200 Mem.Off->print(OS);
1201 OS << ">";
1202 break;
1203 case k_PhysRegister:
1204 OS << "PhysReg<" << PhysReg.Num << ">";
1205 break;
1206 case k_RegisterIndex:
1207 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1208 break;
1209 case k_Token:
1210 OS << Tok.Data;
1211 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001212 case k_RegList:
1213 OS << "RegList< ";
1214 for (auto Reg : (*RegList.List))
1215 OS << Reg << " ";
1216 OS << ">";
1217 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001218 case k_RegPair:
1219 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1220 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001222 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001223}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001224} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001225
Jack Carter9e65aa32013-03-22 00:05:30 +00001226namespace llvm {
1227extern const MCInstrDesc MipsInsts[];
1228}
1229static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1230 return MipsInsts[Opcode];
1231}
1232
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001233static bool hasShortDelaySlot(unsigned Opcode) {
1234 switch (Opcode) {
1235 case Mips::JALS_MM:
1236 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001237 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001238 case Mips::BGEZALS_MM:
1239 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001240 return true;
1241 default:
1242 return false;
1243 }
1244}
1245
Jack Carter9e65aa32013-03-22 00:05:30 +00001246bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001247 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001248 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001249
Jack Carter9e65aa32013-03-22 00:05:30 +00001250 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001251
1252 if (MCID.isBranch() || MCID.isCall()) {
1253 const unsigned Opcode = Inst.getOpcode();
1254 MCOperand Offset;
1255
1256 switch (Opcode) {
1257 default:
1258 break;
Kai Nackee0245392015-01-27 19:11:28 +00001259 case Mips::BBIT0:
1260 case Mips::BBIT032:
1261 case Mips::BBIT1:
1262 case Mips::BBIT132:
1263 assert(hasCnMips() && "instruction only valid for octeon cpus");
1264 // Fall through
1265
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001266 case Mips::BEQ:
1267 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001268 case Mips::BEQ_MM:
1269 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001270 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001271 Offset = Inst.getOperand(2);
1272 if (!Offset.isImm())
1273 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001274 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001275 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001276 if (OffsetToAlignment(Offset.getImm(),
1277 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001278 return Error(IDLoc, "branch to misaligned address");
1279 break;
1280 case Mips::BGEZ:
1281 case Mips::BGTZ:
1282 case Mips::BLEZ:
1283 case Mips::BLTZ:
1284 case Mips::BGEZAL:
1285 case Mips::BLTZAL:
1286 case Mips::BC1F:
1287 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001288 case Mips::BGEZ_MM:
1289 case Mips::BGTZ_MM:
1290 case Mips::BLEZ_MM:
1291 case Mips::BLTZ_MM:
1292 case Mips::BGEZAL_MM:
1293 case Mips::BLTZAL_MM:
1294 case Mips::BC1F_MM:
1295 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001296 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001297 Offset = Inst.getOperand(1);
1298 if (!Offset.isImm())
1299 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001300 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001301 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001302 if (OffsetToAlignment(Offset.getImm(),
1303 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001304 return Error(IDLoc, "branch to misaligned address");
1305 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001306 case Mips::BEQZ16_MM:
1307 case Mips::BNEZ16_MM:
1308 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1309 Offset = Inst.getOperand(1);
1310 if (!Offset.isImm())
1311 break; // We'll deal with this situation later on when applying fixups.
1312 if (!isIntN(8, Offset.getImm()))
1313 return Error(IDLoc, "branch target out of range");
1314 if (OffsetToAlignment(Offset.getImm(), 2LL))
1315 return Error(IDLoc, "branch to misaligned address");
1316 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001317 }
1318 }
1319
Daniel Sandersa84989a2014-06-16 13:25:35 +00001320 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1321 // We still accept it but it is a normal nop.
1322 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1323 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1324 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1325 "nop instruction");
1326 }
1327
Kai Nackee0245392015-01-27 19:11:28 +00001328 if (hasCnMips()) {
1329 const unsigned Opcode = Inst.getOpcode();
1330 MCOperand Opnd;
1331 int Imm;
1332
1333 switch (Opcode) {
1334 default:
1335 break;
1336
1337 case Mips::BBIT0:
1338 case Mips::BBIT032:
1339 case Mips::BBIT1:
1340 case Mips::BBIT132:
1341 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1342 // The offset is handled above
1343 Opnd = Inst.getOperand(1);
1344 if (!Opnd.isImm())
1345 return Error(IDLoc, "expected immediate operand kind");
1346 Imm = Opnd.getImm();
1347 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1348 Opcode == Mips::BBIT1 ? 63 : 31))
1349 return Error(IDLoc, "immediate operand value out of range");
1350 if (Imm > 31) {
1351 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1352 : Mips::BBIT132);
1353 Inst.getOperand(1).setImm(Imm - 32);
1354 }
1355 break;
1356
1357 case Mips::CINS:
1358 case Mips::CINS32:
1359 case Mips::EXTS:
1360 case Mips::EXTS32:
1361 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1362 // Check length
1363 Opnd = Inst.getOperand(3);
1364 if (!Opnd.isImm())
1365 return Error(IDLoc, "expected immediate operand kind");
1366 Imm = Opnd.getImm();
1367 if (Imm < 0 || Imm > 31)
1368 return Error(IDLoc, "immediate operand value out of range");
1369 // Check position
1370 Opnd = Inst.getOperand(2);
1371 if (!Opnd.isImm())
1372 return Error(IDLoc, "expected immediate operand kind");
1373 Imm = Opnd.getImm();
1374 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1375 Opcode == Mips::EXTS ? 63 : 31))
1376 return Error(IDLoc, "immediate operand value out of range");
1377 if (Imm > 31) {
1378 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1379 Inst.getOperand(2).setImm(Imm - 32);
1380 }
1381 break;
1382
1383 case Mips::SEQi:
1384 case Mips::SNEi:
1385 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1386 Opnd = Inst.getOperand(2);
1387 if (!Opnd.isImm())
1388 return Error(IDLoc, "expected immediate operand kind");
1389 Imm = Opnd.getImm();
1390 if (!isInt<10>(Imm))
1391 return Error(IDLoc, "immediate operand value out of range");
1392 break;
1393 }
1394 }
1395
Jack Carter9e65aa32013-03-22 00:05:30 +00001396 if (MCID.mayLoad() || MCID.mayStore()) {
1397 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001398 // reference or immediate we may have to expand instructions.
1399 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001400 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001401 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1402 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001403 MCOperand &Op = Inst.getOperand(i);
1404 if (Op.isImm()) {
1405 int MemOffset = Op.getImm();
1406 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // Offset can't exceed 16bit value.
1408 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001409 return false;
1410 }
1411 } else if (Op.isExpr()) {
1412 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001414 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001415 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001416 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 // Expand symbol.
1418 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001419 return false;
1420 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001421 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001422 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001423 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001424 }
1425 }
1426 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001427 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001428 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001429
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001430 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001431 if (MCID.mayLoad()) {
1432 // Try to create 16-bit GP relative load instruction.
1433 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1434 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1435 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1436 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1437 MCOperand &Op = Inst.getOperand(i);
1438 if (Op.isImm()) {
1439 int MemOffset = Op.getImm();
1440 MCOperand &DstReg = Inst.getOperand(0);
1441 MCOperand &BaseReg = Inst.getOperand(1);
1442 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1443 getContext().getRegisterInfo()->getRegClass(
1444 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1445 BaseReg.getReg() == Mips::GP) {
1446 MCInst TmpInst;
1447 TmpInst.setLoc(IDLoc);
1448 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001449 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1450 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1451 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001452 Instructions.push_back(TmpInst);
1453 return false;
1454 }
1455 }
1456 }
1457 } // for
1458 } // if load
1459
1460 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1461
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001462 MCOperand Opnd;
1463 int Imm;
1464
1465 switch (Inst.getOpcode()) {
1466 default:
1467 break;
1468 case Mips::ADDIUS5_MM:
1469 Opnd = Inst.getOperand(2);
1470 if (!Opnd.isImm())
1471 return Error(IDLoc, "expected immediate operand kind");
1472 Imm = Opnd.getImm();
1473 if (Imm < -8 || Imm > 7)
1474 return Error(IDLoc, "immediate operand value out of range");
1475 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001476 case Mips::ADDIUSP_MM:
1477 Opnd = Inst.getOperand(0);
1478 if (!Opnd.isImm())
1479 return Error(IDLoc, "expected immediate operand kind");
1480 Imm = Opnd.getImm();
1481 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1482 Imm % 4 != 0)
1483 return Error(IDLoc, "immediate operand value out of range");
1484 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001485 case Mips::SLL16_MM:
1486 case Mips::SRL16_MM:
1487 Opnd = Inst.getOperand(2);
1488 if (!Opnd.isImm())
1489 return Error(IDLoc, "expected immediate operand kind");
1490 Imm = Opnd.getImm();
1491 if (Imm < 1 || Imm > 8)
1492 return Error(IDLoc, "immediate operand value out of range");
1493 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001494 case Mips::LI16_MM:
1495 Opnd = Inst.getOperand(1);
1496 if (!Opnd.isImm())
1497 return Error(IDLoc, "expected immediate operand kind");
1498 Imm = Opnd.getImm();
1499 if (Imm < -1 || Imm > 126)
1500 return Error(IDLoc, "immediate operand value out of range");
1501 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001502 case Mips::ADDIUR2_MM:
1503 Opnd = Inst.getOperand(2);
1504 if (!Opnd.isImm())
1505 return Error(IDLoc, "expected immediate operand kind");
1506 Imm = Opnd.getImm();
1507 if (!(Imm == 1 || Imm == -1 ||
1508 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1509 return Error(IDLoc, "immediate operand value out of range");
1510 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001511 case Mips::ADDIUR1SP_MM:
1512 Opnd = Inst.getOperand(1);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (OffsetToAlignment(Imm, 4LL))
1517 return Error(IDLoc, "misaligned immediate operand value");
1518 if (Imm < 0 || Imm > 255)
1519 return Error(IDLoc, "immediate operand value out of range");
1520 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001521 case Mips::ANDI16_MM:
1522 Opnd = Inst.getOperand(2);
1523 if (!Opnd.isImm())
1524 return Error(IDLoc, "expected immediate operand kind");
1525 Imm = Opnd.getImm();
1526 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1527 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1528 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1529 return Error(IDLoc, "immediate operand value out of range");
1530 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001531 case Mips::LBU16_MM:
1532 Opnd = Inst.getOperand(2);
1533 if (!Opnd.isImm())
1534 return Error(IDLoc, "expected immediate operand kind");
1535 Imm = Opnd.getImm();
1536 if (Imm < -1 || Imm > 14)
1537 return Error(IDLoc, "immediate operand value out of range");
1538 break;
1539 case Mips::SB16_MM:
1540 Opnd = Inst.getOperand(2);
1541 if (!Opnd.isImm())
1542 return Error(IDLoc, "expected immediate operand kind");
1543 Imm = Opnd.getImm();
1544 if (Imm < 0 || Imm > 15)
1545 return Error(IDLoc, "immediate operand value out of range");
1546 break;
1547 case Mips::LHU16_MM:
1548 case Mips::SH16_MM:
1549 Opnd = Inst.getOperand(2);
1550 if (!Opnd.isImm())
1551 return Error(IDLoc, "expected immediate operand kind");
1552 Imm = Opnd.getImm();
1553 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1554 return Error(IDLoc, "immediate operand value out of range");
1555 break;
1556 case Mips::LW16_MM:
1557 case Mips::SW16_MM:
1558 Opnd = Inst.getOperand(2);
1559 if (!Opnd.isImm())
1560 return Error(IDLoc, "expected immediate operand kind");
1561 Imm = Opnd.getImm();
1562 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1563 return Error(IDLoc, "immediate operand value out of range");
1564 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001565 case Mips::CACHE:
1566 case Mips::PREF:
1567 Opnd = Inst.getOperand(2);
1568 if (!Opnd.isImm())
1569 return Error(IDLoc, "expected immediate operand kind");
1570 Imm = Opnd.getImm();
1571 if (!isUInt<5>(Imm))
1572 return Error(IDLoc, "immediate operand value out of range");
1573 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001574 case Mips::ADDIUPC_MM:
1575 MCOperand Opnd = Inst.getOperand(1);
1576 if (!Opnd.isImm())
1577 return Error(IDLoc, "expected immediate operand kind");
1578 int Imm = Opnd.getImm();
1579 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1580 return Error(IDLoc, "immediate operand value out of range");
1581 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001582 }
1583 }
1584
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001585 if (needsExpansion(Inst)) {
1586 if (expandInstruction(Inst, IDLoc, Instructions))
1587 return true;
1588 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001589 Instructions.push_back(Inst);
1590
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001591 // If this instruction has a delay slot and .set reorder is active,
1592 // emit a NOP after it.
1593 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1594 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1595
Jack Carter9e65aa32013-03-22 00:05:30 +00001596 return false;
1597}
1598
Jack Carter30a59822012-10-04 04:03:53 +00001599bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1600
Jack Carterd0bd6422013-04-18 00:41:53 +00001601 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001602 case Mips::LoadImm32:
1603 case Mips::LoadImm64:
1604 case Mips::LoadAddrImm32:
1605 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001606 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001607 case Mips::LWM_MM:
1608 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001609 case Mips::JalOneReg:
1610 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 return true;
1612 default:
1613 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001614 }
1615}
Jack Carter92995f12012-10-06 00:53:28 +00001616
Matheus Almeida3813d572014-06-19 14:39:14 +00001617bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001618 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001620 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001621 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001622 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001623 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001624 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001625 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001626 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001627 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001628 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001629 case Mips::B_MM_Pseudo:
1630 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001631 case Mips::SWM_MM:
1632 case Mips::LWM_MM:
1633 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001634 case Mips::JalOneReg:
1635 case Mips::JalTwoReg:
1636 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001637 }
Jack Carter30a59822012-10-04 04:03:53 +00001638}
Jack Carter92995f12012-10-06 00:53:28 +00001639
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001640namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001641template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001642void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001643 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001644 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001645 if (ShiftAmount >= 32) {
1646 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001647 tmpInst.addOperand(MCOperand::createReg(RegNo));
1648 tmpInst.addOperand(MCOperand::createReg(RegNo));
1649 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001650 tmpInst.setLoc(IDLoc);
1651 Instructions.push_back(tmpInst);
1652 tmpInst.clear();
1653 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001654 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001655 tmpInst.addOperand(MCOperand::createReg(RegNo));
1656 tmpInst.addOperand(MCOperand::createReg(RegNo));
1657 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001658 tmpInst.setLoc(IDLoc);
1659 Instructions.push_back(tmpInst);
1660 tmpInst.clear();
1661 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001662 // There's no need for an ORi if the immediate is 0.
1663 if (Operand.isImm() && Operand.getImm() == 0)
1664 return;
1665
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001666 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001667 tmpInst.addOperand(MCOperand::createReg(RegNo));
1668 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001669 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001670 tmpInst.setLoc(IDLoc);
1671 Instructions.push_back(tmpInst);
1672}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001673
Toma Tabacua2861db2015-05-01 10:26:47 +00001674template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001675void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001676 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001677 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001678 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001679}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001680}
1681
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001682bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1683 SmallVectorImpl<MCInst> &Instructions) {
1684 // Create a JALR instruction which is going to replace the pseudo-JAL.
1685 MCInst JalrInst;
1686 JalrInst.setLoc(IDLoc);
1687 const MCOperand FirstRegOp = Inst.getOperand(0);
1688 const unsigned Opcode = Inst.getOpcode();
1689
1690 if (Opcode == Mips::JalOneReg) {
1691 // jal $rs => jalr $rs
1692 if (inMicroMipsMode()) {
1693 JalrInst.setOpcode(Mips::JALR16_MM);
1694 JalrInst.addOperand(FirstRegOp);
1695 } else {
1696 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001697 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001698 JalrInst.addOperand(FirstRegOp);
1699 }
1700 } else if (Opcode == Mips::JalTwoReg) {
1701 // jal $rd, $rs => jalr $rd, $rs
1702 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1703 JalrInst.addOperand(FirstRegOp);
1704 const MCOperand SecondRegOp = Inst.getOperand(1);
1705 JalrInst.addOperand(SecondRegOp);
1706 }
1707 Instructions.push_back(JalrInst);
1708
1709 // If .set reorder is active, emit a NOP after it.
1710 if (AssemblerOptions.back()->isReorder()) {
1711 // This is a 32-bit NOP because these 2 pseudo-instructions
1712 // do not have a short delay slot.
1713 MCInst NopInst;
1714 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001715 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1716 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1717 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001718 Instructions.push_back(NopInst);
1719 }
1720
1721 return false;
1722}
1723
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001724bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1725 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001727 if (!Is32BitImm && !isGP64bit()) {
1728 Error(IDLoc, "instruction requires a 64-bit architecture");
1729 return true;
1730 }
1731
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001732 bool UseSrcReg = false;
1733 if (SrcReg != Mips::NoRegister)
1734 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001735
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001736 MCInst tmpInst;
1737
Jack Carter92995f12012-10-06 00:53:28 +00001738 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001739 // FIXME: gas has a special case for values that are 000...1111, which
1740 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001741 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001742 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001743 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001744 if (!UseSrcReg)
1745 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001746 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001747 tmpInst.addOperand(MCOperand::createReg(DstReg));
1748 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1749 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001750 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001752 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001753 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001754 if (!UseSrcReg)
1755 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001756 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001757 tmpInst.addOperand(MCOperand::createReg(DstReg));
1758 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1759 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001760 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001761 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001762 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001763 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001764 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001765 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1766 uint16_t Bits15To0 = ImmValue & 0xffff;
1767
Jack Carter873c7242013-01-12 01:03:14 +00001768 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001769 tmpInst.addOperand(MCOperand::createReg(DstReg));
1770 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
Jack Carter30a59822012-10-04 04:03:53 +00001771 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001772 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1773
1774 if (UseSrcReg)
1775 createAddu(DstReg, DstReg, SrcReg, Instructions);
1776
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001777 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001778 if (Is32BitImm) {
1779 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001780 return true;
1781 }
1782
1783 // <------- lo32 ------>
1784 // <------- hi32 ------>
1785 // <- hi16 -> <- lo16 ->
1786 // _________________________________
1787 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001788 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001789 // |__________|__________|__________|
1790 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001791 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001792 // li d,j => lui d,hi16(j)
1793 // ori d,d,hi16(lo32(j))
1794 // dsll d,d,16
1795 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001796 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1797 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1798 uint16_t Bits15To0 = ImmValue & 0xffff;
1799
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001800 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001801 tmpInst.addOperand(MCOperand::createReg(DstReg));
1802 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001803 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001804 createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions);
1805 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
1806
1807 if (UseSrcReg)
1808 createAddu(DstReg, DstReg, SrcReg, Instructions);
1809
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001810 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001811 if (Is32BitImm) {
1812 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001813 return true;
1814 }
1815
1816 // <------- hi32 ------> <------- lo32 ------>
1817 // <- hi16 -> <- lo16 ->
1818 // ___________________________________________
1819 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001820 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001821 // |__________|__________|__________|__________|
1822 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001823 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001824 // li d,j => lui d,hi16(j)
1825 // ori d,d,lo16(hi32(j))
1826 // dsll d,d,16
1827 // ori d,d,hi16(lo32(j))
1828 // dsll d,d,16
1829 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001830 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1831 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1832 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1833 uint16_t Bits15To0 = ImmValue & 0xffff;
1834
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001835 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001836 tmpInst.addOperand(MCOperand::createReg(DstReg));
1837 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001838 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001839 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001840
1841 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1842 // two left shifts of 16 bits.
1843 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001844 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001845 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001846 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1847 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001848 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001849
1850 if (UseSrcReg)
1851 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001852 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001853 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001854}
Jack Carter92995f12012-10-06 00:53:28 +00001855
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001856bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1857 SmallVectorImpl<MCInst> &Instructions) {
1858 const MCOperand &ImmOp = Inst.getOperand(1);
1859 assert(ImmOp.isImm() && "expected immediate operand kind");
1860 const MCOperand &DstRegOp = Inst.getOperand(0);
1861 assert(DstRegOp.isReg() && "expected register operand kind");
1862
1863 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1864 Is32BitImm, IDLoc, Instructions))
1865 return true;
1866
1867 return false;
1868}
1869
Matheus Almeida3813d572014-06-19 14:39:14 +00001870bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001871MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001872 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001873 const MCOperand &DstRegOp = Inst.getOperand(0);
1874 assert(DstRegOp.isReg() && "expected register operand kind");
1875
Jack Carter543fdf82012-10-09 23:29:45 +00001876 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001877 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1878 "expected immediate operand kind");
1879 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001880 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001881 return false;
1882 }
Jack Carter543fdf82012-10-09 23:29:45 +00001883 const MCOperand &SrcRegOp = Inst.getOperand(1);
1884 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001885
1886 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1887 Is32BitImm, IDLoc, Instructions))
1888 return true;
1889
Matheus Almeida3813d572014-06-19 14:39:14 +00001890 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001891}
1892
Matheus Almeida3813d572014-06-19 14:39:14 +00001893bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001894MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001895 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001896 const MCOperand &DstRegOp = Inst.getOperand(0);
1897 assert(DstRegOp.isReg() && "expected register operand kind");
1898
Jack Carter543fdf82012-10-09 23:29:45 +00001899 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001900 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1901 "expected immediate operand kind");
1902 if (!ImmOp.isImm()) {
Toma Tabacuec1de822015-05-14 10:53:40 +00001903 expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001904 return false;
1905 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001906
1907 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1908 Is32BitImm, IDLoc, Instructions))
1909 return true;
1910
Matheus Almeida3813d572014-06-19 14:39:14 +00001911 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001912}
1913
Toma Tabacuec1de822015-05-14 10:53:40 +00001914void MipsAsmParser::expandLoadAddressSym(
1915 const MCOperand &DstRegOp, const MCOperand &SymOp, bool Is32BitSym,
1916 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1917 if (Is32BitSym && isABI_N64())
1918 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
1919
Toma Tabacu0d64b202014-08-14 10:29:17 +00001920 MCInst tmpInst;
Toma Tabacub5592ee2015-05-14 10:02:58 +00001921 unsigned RegNo = DstRegOp.getReg();
Toma Tabacu0d64b202014-08-14 10:29:17 +00001922 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1923 const MCSymbolRefExpr *HiExpr =
1924 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1925 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1926 const MCSymbolRefExpr *LoExpr =
1927 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1928 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
Toma Tabacuec1de822015-05-14 10:53:40 +00001929 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001930 // If it's a 64-bit architecture, expand to:
1931 // la d,sym => lui d,highest(sym)
1932 // ori d,d,higher(sym)
1933 // dsll d,d,16
1934 // ori d,d,hi16(sym)
1935 // dsll d,d,16
1936 // ori d,d,lo16(sym)
1937 const MCSymbolRefExpr *HighestExpr =
1938 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1939 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1940 const MCSymbolRefExpr *HigherExpr =
1941 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1942 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1943
1944 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001945 tmpInst.addOperand(MCOperand::createReg(RegNo));
1946 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001947 Instructions.push_back(tmpInst);
1948
Jim Grosbache9119e42015-05-13 18:37:00 +00001949 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001950 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001951 createLShiftOri<16>(MCOperand::createExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001952 Instructions);
Jim Grosbache9119e42015-05-13 18:37:00 +00001953 createLShiftOri<16>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001954 Instructions);
1955 } else {
1956 // Otherwise, expand to:
1957 // la d,sym => lui d,hi16(sym)
1958 // ori d,d,lo16(sym)
1959 tmpInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001960 tmpInst.addOperand(MCOperand::createReg(RegNo));
1961 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001962 Instructions.push_back(tmpInst);
1963
Jim Grosbache9119e42015-05-13 18:37:00 +00001964 createLShiftOri<0>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00001965 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001966 }
1967}
1968
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001969bool MipsAsmParser::expandUncondBranchMMPseudo(
1970 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001971 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1972 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001973
1974 MCOperand Offset = Inst.getOperand(0);
1975 if (Offset.isExpr()) {
1976 Inst.clear();
1977 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001978 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
1979 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
1980 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001981 } else {
1982 assert(Offset.isImm() && "expected immediate operand kind");
1983 if (isIntN(11, Offset.getImm())) {
1984 // If offset fits into 11 bits then this instruction becomes microMIPS
1985 // 16-bit unconditional branch instruction.
1986 Inst.setOpcode(Mips::B16_MM);
1987 } else {
1988 if (!isIntN(17, Offset.getImm()))
1989 Error(IDLoc, "branch target out of range");
1990 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1991 Error(IDLoc, "branch to misaligned address");
1992 Inst.clear();
1993 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001994 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
1995 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
1996 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001997 }
1998 }
1999 Instructions.push_back(Inst);
2000
Toma Tabacu234482a2015-03-16 12:03:39 +00002001 // If .set reorder is active, emit a NOP after the branch instruction.
2002 if (AssemblerOptions.back()->isReorder())
2003 createNop(true, IDLoc, Instructions);
2004
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002005 return false;
2006}
2007
Jack Carter9e65aa32013-03-22 00:05:30 +00002008void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002009 SmallVectorImpl<MCInst> &Instructions,
2010 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002011 const MCSymbolRefExpr *SR;
2012 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002013 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002014 const MCExpr *ExprOffset;
2015 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002016 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002017 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2018 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002019 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002020 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2021 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002022 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002023 if (isImmOpnd) {
2024 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2025 ImmOffset = Inst.getOperand(2).getImm();
2026 LoOffset = ImmOffset & 0x0000ffff;
2027 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002028 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002029 if (LoOffset & 0x8000)
2030 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002031 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002032 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002033 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002034 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002035 // These are some of the types of expansions we perform here:
2036 // 1) lw $8, sym => lui $8, %hi(sym)
2037 // lw $8, %lo(sym)($8)
2038 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2039 // add $8, $8, $9
2040 // lw $8, %lo(offset)($9)
2041 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2042 // add $at, $at, $8
2043 // lw $8, %lo(offset)($at)
2044 // 4) sw $8, sym => lui $at, %hi(sym)
2045 // sw $8, %lo(sym)($at)
2046 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2047 // add $at, $at, $8
2048 // sw $8, %lo(offset)($at)
2049 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2050 // ldc1 $f0, %lo(sym)($at)
2051 //
2052 // For load instructions we can use the destination register as a temporary
2053 // if base and dst are different (examples 1 and 2) and if the base register
2054 // is general purpose otherwise we must use $at (example 6) and error if it's
2055 // not available. For stores we must use $at (examples 4 and 5) because we
2056 // must not clobber the source register setting up the offset.
2057 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2058 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2059 unsigned RegClassIDOp0 =
2060 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2061 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2062 (RegClassIDOp0 == Mips::GPR64RegClassID);
2063 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002064 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002065 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002066 // At this point we need AT to perform the expansions and we exit if it is
2067 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002068 TmpRegNum = getATReg(IDLoc);
2069 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002070 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002071 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002072
Jack Carter9e65aa32013-03-22 00:05:30 +00002073 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002074 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002075 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002076 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002077 else {
2078 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002079 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2081 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2082 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002083 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002084 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002085 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jim Grosbache9119e42015-05-13 18:37:00 +00002086 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002087 }
2088 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002090 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002091 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002092 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002094 if (BaseRegNum != Mips::ZERO) {
2095 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002096 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2097 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2098 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002099 Instructions.push_back(TempInst);
2100 TempInst.clear();
2101 }
Alp Tokercb402912014-01-24 17:20:08 +00002102 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002104 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002105 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2106 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002107 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002108 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002109 else {
2110 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002111 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2112 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2113 getContext());
Jim Grosbache9119e42015-05-13 18:37:00 +00002114 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002115 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jim Grosbache9119e42015-05-13 18:37:00 +00002117 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002118 }
2119 }
2120 Instructions.push_back(TempInst);
2121 TempInst.clear();
2122}
2123
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002124bool
2125MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2126 SmallVectorImpl<MCInst> &Instructions) {
2127 unsigned OpNum = Inst.getNumOperands();
2128 unsigned Opcode = Inst.getOpcode();
2129 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2130
2131 assert (Inst.getOperand(OpNum - 1).isImm() &&
2132 Inst.getOperand(OpNum - 2).isReg() &&
2133 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2134
2135 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2136 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2137 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2138 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2139 // It can be implemented as SWM16 or LWM16 instruction.
2140 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2141
2142 Inst.setOpcode(NewOpcode);
2143 Instructions.push_back(Inst);
2144 return false;
2145}
2146
Toma Tabacu234482a2015-03-16 12:03:39 +00002147void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2148 SmallVectorImpl<MCInst> &Instructions) {
2149 MCInst NopInst;
2150 if (hasShortDelaySlot) {
2151 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002152 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2153 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002154 } else {
2155 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002156 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2157 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2158 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002159 }
2160 Instructions.push_back(NopInst);
2161}
2162
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002163void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2164 unsigned TrgReg,
2165 SmallVectorImpl<MCInst> &Instructions) {
2166 MCInst AdduInst;
2167 AdduInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002168 AdduInst.addOperand(MCOperand::createReg(DstReg));
2169 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2170 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002171 Instructions.push_back(AdduInst);
2172}
2173
Matheus Almeida595fcab2014-06-11 15:05:56 +00002174unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2175 // As described by the Mips32r2 spec, the registers Rd and Rs for
2176 // jalr.hb must be different.
2177 unsigned Opcode = Inst.getOpcode();
2178
2179 if (Opcode == Mips::JALR_HB &&
2180 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2181 return Match_RequiresDifferentSrcAndDst;
2182
2183 return Match_Success;
2184}
2185
David Blaikie960ea3f2014-06-08 16:18:35 +00002186bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2187 OperandVector &Operands,
2188 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002189 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002190 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002191
Jack Carterb4dbc172012-09-05 23:34:03 +00002192 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002193 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002194 unsigned MatchResult =
2195 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002196
2197 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002198 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002199 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002200 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002201 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002202 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002203 return false;
2204 }
2205 case Match_MissingFeature:
2206 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2207 return true;
2208 case Match_InvalidOperand: {
2209 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002210 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002211 if (ErrorInfo >= Operands.size())
2212 return Error(IDLoc, "too few operands for instruction");
2213
David Blaikie960ea3f2014-06-08 16:18:35 +00002214 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002215 if (ErrorLoc == SMLoc())
2216 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002217 }
2218
2219 return Error(ErrorLoc, "invalid operand for instruction");
2220 }
2221 case Match_MnemonicFail:
2222 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002223 case Match_RequiresDifferentSrcAndDst:
2224 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002225 }
Craig Topper589ceee2015-01-03 08:16:34 +00002226
2227 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002228}
2229
Toma Tabacud9d344b2015-04-27 14:05:04 +00002230void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2231 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2232 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2233 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002234}
2235
Daniel Sandersef638fe2014-10-03 15:37:37 +00002236void
2237MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2238 SMRange Range, bool ShowColors) {
2239 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002240 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002241 ShowColors);
2242}
2243
Jack Carter1ac53222013-02-20 23:11:17 +00002244int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002245 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002246
Vladimir Medic4c299852013-11-06 11:27:05 +00002247 CC = StringSwitch<unsigned>(Name)
2248 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002249 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002250 .Case("a0", 4)
2251 .Case("a1", 5)
2252 .Case("a2", 6)
2253 .Case("a3", 7)
2254 .Case("v0", 2)
2255 .Case("v1", 3)
2256 .Case("s0", 16)
2257 .Case("s1", 17)
2258 .Case("s2", 18)
2259 .Case("s3", 19)
2260 .Case("s4", 20)
2261 .Case("s5", 21)
2262 .Case("s6", 22)
2263 .Case("s7", 23)
2264 .Case("k0", 26)
2265 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002266 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002267 .Case("sp", 29)
2268 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002269 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002270 .Case("ra", 31)
2271 .Case("t0", 8)
2272 .Case("t1", 9)
2273 .Case("t2", 10)
2274 .Case("t3", 11)
2275 .Case("t4", 12)
2276 .Case("t5", 13)
2277 .Case("t6", 14)
2278 .Case("t7", 15)
2279 .Case("t8", 24)
2280 .Case("t9", 25)
2281 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002282
Toma Tabacufda445c2014-09-15 15:33:01 +00002283 if (!(isABI_N32() || isABI_N64()))
2284 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002285
Daniel Sandersef638fe2014-10-03 15:37:37 +00002286 if (12 <= CC && CC <= 15) {
2287 // Name is one of t4-t7
2288 AsmToken RegTok = getLexer().peekTok();
2289 SMRange RegRange = RegTok.getLocRange();
2290
2291 StringRef FixedName = StringSwitch<StringRef>(Name)
2292 .Case("t4", "t0")
2293 .Case("t5", "t1")
2294 .Case("t6", "t2")
2295 .Case("t7", "t3")
2296 .Default("");
2297 assert(FixedName != "" && "Register name is not one of t4-t7.");
2298
2299 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2300 "Did you mean $" + FixedName + "?", RegRange);
2301 }
2302
Toma Tabacufda445c2014-09-15 15:33:01 +00002303 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2304 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2305 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2306 if (8 <= CC && CC <= 11)
2307 CC += 4;
2308
2309 if (CC == -1)
2310 CC = StringSwitch<unsigned>(Name)
2311 .Case("a4", 8)
2312 .Case("a5", 9)
2313 .Case("a6", 10)
2314 .Case("a7", 11)
2315 .Case("kt0", 26)
2316 .Case("kt1", 27)
2317 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002318
2319 return CC;
2320}
Jack Carterd0bd6422013-04-18 00:41:53 +00002321
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002322int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2323 int CC;
2324
2325 CC = StringSwitch<unsigned>(Name)
2326 .Case("hwr_cpunum", 0)
2327 .Case("hwr_synci_step", 1)
2328 .Case("hwr_cc", 2)
2329 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002330 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002331 .Default(-1);
2332
2333 return CC;
2334}
2335
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002336int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002337
Jack Cartera63b16a2012-09-07 00:23:42 +00002338 if (Name[0] == 'f') {
2339 StringRef NumString = Name.substr(1);
2340 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002341 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002342 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002343 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002344 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002345 return IntVal;
2346 }
2347 return -1;
2348}
Jack Cartera63b16a2012-09-07 00:23:42 +00002349
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002350int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2351
2352 if (Name.startswith("fcc")) {
2353 StringRef NumString = Name.substr(3);
2354 unsigned IntVal;
2355 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002356 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002357 if (IntVal > 7) // There are only 8 fcc registers.
2358 return -1;
2359 return IntVal;
2360 }
2361 return -1;
2362}
2363
2364int MipsAsmParser::matchACRegisterName(StringRef Name) {
2365
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002366 if (Name.startswith("ac")) {
2367 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002368 unsigned IntVal;
2369 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002370 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002371 if (IntVal > 3) // There are only 3 acc registers.
2372 return -1;
2373 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002374 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002375 return -1;
2376}
Jack Carterd0bd6422013-04-18 00:41:53 +00002377
Jack Carter5dc8ac92013-09-25 23:50:44 +00002378int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2379 unsigned IntVal;
2380
2381 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2382 return -1;
2383
2384 if (IntVal > 31)
2385 return -1;
2386
2387 return IntVal;
2388}
2389
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002390int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2391 int CC;
2392
2393 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002394 .Case("msair", 0)
2395 .Case("msacsr", 1)
2396 .Case("msaaccess", 2)
2397 .Case("msasave", 3)
2398 .Case("msamodify", 4)
2399 .Case("msarequest", 5)
2400 .Case("msamap", 6)
2401 .Case("msaunmap", 7)
2402 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002403
2404 return CC;
2405}
2406
Toma Tabacu89a712b2015-04-15 10:48:56 +00002407unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002408 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002409 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002410 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002411 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002412 return 0;
2413 }
2414 unsigned AT = getReg(
2415 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002416 return AT;
2417}
Jack Carter0b744b32012-10-04 02:29:46 +00002418
Jack Carterd0bd6422013-04-18 00:41:53 +00002419unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002420 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002421}
2422
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002423unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002424 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002425 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002426}
2427
Jack Carter873c7242013-01-12 01:03:14 +00002428int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002429 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002430 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002431 return -1;
2432
Jack Carter873c7242013-01-12 01:03:14 +00002433 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002434}
2435
Toma Tabacu13964452014-09-04 13:23:44 +00002436bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002437 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002438 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002439
Jack Carter30a59822012-10-04 04:03:53 +00002440 // Check if the current operand has a custom associated parser, if so, try to
2441 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002442 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2443 if (ResTy == MatchOperand_Success)
2444 return false;
2445 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2446 // there was a match, but an error occurred, in which case, just return that
2447 // the operand parsing failed.
2448 if (ResTy == MatchOperand_ParseFail)
2449 return true;
2450
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002451 DEBUG(dbgs() << ".. Generic Parser\n");
2452
Jack Carterb4dbc172012-09-05 23:34:03 +00002453 switch (getLexer().getKind()) {
2454 default:
2455 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2456 return true;
2457 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002458 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002459 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002460
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002461 // Almost all registers have been parsed by custom parsers. There is only
2462 // one exception to this. $zero (and it's alias $0) will reach this point
2463 // for div, divu, and similar instructions because it is not an operand
2464 // to the instruction definition but an explicit register. Special case
2465 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002466 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002467 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002468
Jack Carterd0bd6422013-04-18 00:41:53 +00002469 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002470 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002471 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002472 return true;
2473
Jack Carter873c7242013-01-12 01:03:14 +00002474 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002475 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002476 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002477 const MCExpr *Res =
2478 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002479
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002480 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002481 return false;
2482 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002483 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002484 case AsmToken::LParen:
2485 case AsmToken::Minus:
2486 case AsmToken::Plus:
2487 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002488 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002489 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002490 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002491 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002492 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002493 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002494 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002495 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002496 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002497 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002498 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002499 return true;
2500
Jack Carter873c7242013-01-12 01:03:14 +00002501 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2502
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002503 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002504 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002505 } // case AsmToken::Percent
2506 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002507 return true;
2508}
2509
Vladimir Medic4c299852013-11-06 11:27:05 +00002510const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002511 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002512 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002513 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002514 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002515 // It's a constant, evaluate reloc value.
2516 int16_t Val;
2517 switch (getVariantKind(RelocStr)) {
2518 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2519 // Get the 1st 16-bits.
2520 Val = MCE->getValue() & 0xffff;
2521 break;
2522 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2523 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2524 // 16 bits being negative.
2525 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2526 break;
2527 case MCSymbolRefExpr::VK_Mips_HIGHER:
2528 // Get the 3rd 16-bits.
2529 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2530 break;
2531 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2532 // Get the 4th 16-bits.
2533 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2534 break;
2535 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002536 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002537 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002538 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002539 }
2540
Jack Carterb5cf5902013-04-17 00:18:04 +00002541 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002542 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002543 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002544 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002545 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002546 return Res;
2547 }
2548
2549 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002550 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2551
Sasa Stankovic06c47802014-04-03 10:37:45 +00002552 // Try to create target expression.
2553 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2554 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002555
Jack Carterd0bd6422013-04-18 00:41:53 +00002556 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2557 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002558 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2559 return Res;
2560 }
2561
2562 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002563 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2564 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2565 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002566 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002568 return Expr;
2569}
2570
2571bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2572
2573 switch (Expr->getKind()) {
2574 case MCExpr::Constant:
2575 return true;
2576 case MCExpr::SymbolRef:
2577 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2578 case MCExpr::Binary:
2579 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2580 if (!isEvaluated(BE->getLHS()))
2581 return false;
2582 return isEvaluated(BE->getRHS());
2583 }
2584 case MCExpr::Unary:
2585 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002586 case MCExpr::Target:
2587 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002588 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002589 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002590}
Jack Carterd0bd6422013-04-18 00:41:53 +00002591
Jack Carterb5cf5902013-04-17 00:18:04 +00002592bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002593 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002594 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002595 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002596 if (Tok.isNot(AsmToken::Identifier))
2597 return true;
2598
Yaron Keren075759a2015-03-30 15:42:36 +00002599 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002600
Jack Carterd0bd6422013-04-18 00:41:53 +00002601 Parser.Lex(); // Eat the identifier.
2602 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002603 const MCExpr *IdVal;
2604 SMLoc EndLoc;
2605
2606 if (getLexer().getKind() == AsmToken::LParen) {
2607 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002608 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002609 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002610 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002611 const AsmToken &nextTok = Parser.getTok();
2612 if (nextTok.isNot(AsmToken::Identifier))
2613 return true;
2614 Str += "(%";
2615 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002617 if (getLexer().getKind() != AsmToken::LParen)
2618 return true;
2619 } else
2620 break;
2621 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002622 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002623 return true;
2624
2625 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002626 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002627
2628 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002629 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002630
Jack Carterd0bd6422013-04-18 00:41:53 +00002631 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002632 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002633}
2634
Jack Carterb4dbc172012-09-05 23:34:03 +00002635bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2636 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002637 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002638 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002639 if (ResTy == MatchOperand_Success) {
2640 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002641 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002642 StartLoc = Operand.getStartLoc();
2643 EndLoc = Operand.getEndLoc();
2644
2645 // AFAIK, we only support numeric registers and named GPR's in CFI
2646 // directives.
2647 // Don't worry about eating tokens before failing. Using an unrecognised
2648 // register is a parse error.
2649 if (Operand.isGPRAsmReg()) {
2650 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002651 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002652 }
2653
2654 return (RegNo == (unsigned)-1);
2655 }
2656
2657 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002658 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002659}
2660
Jack Carterb5cf5902013-04-17 00:18:04 +00002661bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002662 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002663 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002664 bool Result = true;
2665
2666 while (getLexer().getKind() == AsmToken::LParen)
2667 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002668
Jack Carterd0bd6422013-04-18 00:41:53 +00002669 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002670 default:
2671 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002672 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002673 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002674 case AsmToken::Integer:
2675 case AsmToken::Minus:
2676 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002677 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002678 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002679 else
2680 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002681 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002682 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002683 break;
Jack Carter873c7242013-01-12 01:03:14 +00002684 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002685 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002686 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002687 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002688}
2689
David Blaikie960ea3f2014-06-08 16:18:35 +00002690MipsAsmParser::OperandMatchResultTy
2691MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002692 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002693 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002694 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002695 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002696 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002697 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002698 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002699 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002700
Jack Carterb5cf5902013-04-17 00:18:04 +00002701 if (getLexer().getKind() == AsmToken::LParen) {
2702 Parser.Lex();
2703 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002704 }
2705
Jack Carterb5cf5902013-04-17 00:18:04 +00002706 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002707 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002708 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002709
Jack Carterd0bd6422013-04-18 00:41:53 +00002710 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002711 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002712 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2713 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002714 SMLoc E =
2715 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002716 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002717 return MatchOperand_Success;
2718 }
2719 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002720 SMLoc E =
2721 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002722
Jack Carterd0bd6422013-04-18 00:41:53 +00002723 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002724 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002725 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002726 S, E, *this);
2727 Operands.push_back(
2728 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002729 return MatchOperand_Success;
2730 }
2731 Error(Parser.getTok().getLoc(), "'(' expected");
2732 return MatchOperand_ParseFail;
2733 }
2734
Jack Carterd0bd6422013-04-18 00:41:53 +00002735 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002736 }
2737
Toma Tabacu13964452014-09-04 13:23:44 +00002738 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002739 if (Res != MatchOperand_Success)
2740 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002741
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002742 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002743 Error(Parser.getTok().getLoc(), "')' expected");
2744 return MatchOperand_ParseFail;
2745 }
2746
Jack Carter873c7242013-01-12 01:03:14 +00002747 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2748
Jack Carterd0bd6422013-04-18 00:41:53 +00002749 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002750
Craig Topper062a2ba2014-04-25 05:30:21 +00002751 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002752 IdVal = MCConstantExpr::Create(0, getContext());
2753
Jack Carterd0bd6422013-04-18 00:41:53 +00002754 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002755 std::unique_ptr<MipsOperand> op(
2756 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002757 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002758 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002759 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002760 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002761 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2762 int64_t Imm;
2763 if (IdVal->EvaluateAsAbsolute(Imm))
2764 IdVal = MCConstantExpr::Create(Imm, getContext());
2765 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2766 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2767 getContext());
2768 }
2769
David Blaikie960ea3f2014-06-08 16:18:35 +00002770 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002771 return MatchOperand_Success;
2772}
2773
David Blaikie960ea3f2014-06-08 16:18:35 +00002774bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002775 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002776 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2777 if (Sym) {
2778 SMLoc S = Parser.getTok().getLoc();
2779 const MCExpr *Expr;
2780 if (Sym->isVariable())
2781 Expr = Sym->getVariableValue();
2782 else
2783 return false;
2784 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002785 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002786 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002787 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002788 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002789 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002790 if (ResTy == MatchOperand_Success) {
2791 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002792 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002793 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002794 llvm_unreachable("Should never ParseFail");
2795 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002796 }
2797 } else if (Expr->getKind() == MCExpr::Constant) {
2798 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002799 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002800 Operands.push_back(
2801 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002802 return true;
2803 }
2804 }
2805 return false;
2806}
Jack Carterd0bd6422013-04-18 00:41:53 +00002807
Jack Carter873c7242013-01-12 01:03:14 +00002808MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002809MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002810 StringRef Identifier,
2811 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002812 int Index = matchCPURegisterName(Identifier);
2813 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002814 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002815 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2816 return MatchOperand_Success;
2817 }
2818
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002819 Index = matchHWRegsRegisterName(Identifier);
2820 if (Index != -1) {
2821 Operands.push_back(MipsOperand::createHWRegsReg(
2822 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2823 return MatchOperand_Success;
2824 }
2825
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002826 Index = matchFPURegisterName(Identifier);
2827 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002828 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002829 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2830 return MatchOperand_Success;
2831 }
2832
2833 Index = matchFCCRegisterName(Identifier);
2834 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002835 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002836 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2837 return MatchOperand_Success;
2838 }
2839
2840 Index = matchACRegisterName(Identifier);
2841 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002842 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002843 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2844 return MatchOperand_Success;
2845 }
2846
2847 Index = matchMSA128RegisterName(Identifier);
2848 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002849 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002850 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2851 return MatchOperand_Success;
2852 }
2853
2854 Index = matchMSA128CtrlRegisterName(Identifier);
2855 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002856 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002857 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2858 return MatchOperand_Success;
2859 }
2860
2861 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002862}
2863
2864MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002865MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002866 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002867 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002868
2869 if (Token.is(AsmToken::Identifier)) {
2870 DEBUG(dbgs() << ".. identifier\n");
2871 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002872 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002873 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002874 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002875 } else if (Token.is(AsmToken::Integer)) {
2876 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002877 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002878 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2879 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002880 return MatchOperand_Success;
2881 }
2882
2883 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2884
2885 return MatchOperand_NoMatch;
2886}
2887
David Blaikie960ea3f2014-06-08 16:18:35 +00002888MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002889MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002890 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002891 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002892
2893 auto Token = Parser.getTok();
2894
2895 SMLoc S = Token.getLoc();
2896
2897 if (Token.isNot(AsmToken::Dollar)) {
2898 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2899 if (Token.is(AsmToken::Identifier)) {
2900 if (searchSymbolAlias(Operands))
2901 return MatchOperand_Success;
2902 }
2903 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2904 return MatchOperand_NoMatch;
2905 }
2906 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002907
Toma Tabacu13964452014-09-04 13:23:44 +00002908 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002909 if (ResTy == MatchOperand_Success) {
2910 Parser.Lex(); // $
2911 Parser.Lex(); // identifier
2912 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002913 return ResTy;
2914}
2915
2916MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002917MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002918 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002919 switch (getLexer().getKind()) {
2920 default:
2921 return MatchOperand_NoMatch;
2922 case AsmToken::LParen:
2923 case AsmToken::Minus:
2924 case AsmToken::Plus:
2925 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002926 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002927 case AsmToken::String:
2928 break;
2929 }
2930
2931 const MCExpr *IdVal;
2932 SMLoc S = Parser.getTok().getLoc();
2933 if (getParser().parseExpression(IdVal))
2934 return MatchOperand_ParseFail;
2935
2936 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2937 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2938 return MatchOperand_Success;
2939}
2940
David Blaikie960ea3f2014-06-08 16:18:35 +00002941MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002942MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002943 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002944 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002945
2946 SMLoc S = getLexer().getLoc();
2947
2948 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002949 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002950 if (ResTy != MatchOperand_NoMatch)
2951 return ResTy;
2952
Daniel Sanders315386c2014-04-01 10:40:14 +00002953 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002954 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002955 if (ResTy != MatchOperand_NoMatch)
2956 return ResTy;
2957
Daniel Sandersffd84362014-04-01 10:41:48 +00002958 const MCExpr *Expr = nullptr;
2959 if (Parser.parseExpression(Expr)) {
2960 // We have no way of knowing if a symbol was consumed so we must ParseFail
2961 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002962 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002963 Operands.push_back(
2964 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002965 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002966}
2967
Vladimir Medic2b953d02013-10-01 09:48:56 +00002968MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002969MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002970 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002971 const MCExpr *IdVal;
2972 // If the first token is '$' we may have register operand.
2973 if (Parser.getTok().is(AsmToken::Dollar))
2974 return MatchOperand_NoMatch;
2975 SMLoc S = Parser.getTok().getLoc();
2976 if (getParser().parseExpression(IdVal))
2977 return MatchOperand_ParseFail;
2978 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002979 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002980 int64_t Val = MCE->getValue();
2981 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2982 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002983 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002984 return MatchOperand_Success;
2985}
2986
Matheus Almeida779c5932013-11-18 12:32:49 +00002987MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002988MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002989 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002990 switch (getLexer().getKind()) {
2991 default:
2992 return MatchOperand_NoMatch;
2993 case AsmToken::LParen:
2994 case AsmToken::Plus:
2995 case AsmToken::Minus:
2996 case AsmToken::Integer:
2997 break;
2998 }
2999
3000 const MCExpr *Expr;
3001 SMLoc S = Parser.getTok().getLoc();
3002
3003 if (getParser().parseExpression(Expr))
3004 return MatchOperand_ParseFail;
3005
3006 int64_t Val;
3007 if (!Expr->EvaluateAsAbsolute(Val)) {
3008 Error(S, "expected immediate value");
3009 return MatchOperand_ParseFail;
3010 }
3011
3012 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3013 // and because the CPU always adds one to the immediate field, the allowed
3014 // range becomes 1..4. We'll only check the range here and will deal
3015 // with the addition/subtraction when actually decoding/encoding
3016 // the instruction.
3017 if (Val < 1 || Val > 4) {
3018 Error(S, "immediate not in range (1..4)");
3019 return MatchOperand_ParseFail;
3020 }
3021
Jack Carter3b2c96e2014-01-22 23:31:38 +00003022 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003023 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003024 return MatchOperand_Success;
3025}
3026
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003027MipsAsmParser::OperandMatchResultTy
3028MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3029 MCAsmParser &Parser = getParser();
3030 SmallVector<unsigned, 10> Regs;
3031 unsigned RegNo;
3032 unsigned PrevReg = Mips::NoRegister;
3033 bool RegRange = false;
3034 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3035
3036 if (Parser.getTok().isNot(AsmToken::Dollar))
3037 return MatchOperand_ParseFail;
3038
3039 SMLoc S = Parser.getTok().getLoc();
3040 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3041 SMLoc E = getLexer().getLoc();
3042 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3043 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3044 if (RegRange) {
3045 // Remove last register operand because registers from register range
3046 // should be inserted first.
3047 if (RegNo == Mips::RA) {
3048 Regs.push_back(RegNo);
3049 } else {
3050 unsigned TmpReg = PrevReg + 1;
3051 while (TmpReg <= RegNo) {
3052 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3053 Error(E, "invalid register operand");
3054 return MatchOperand_ParseFail;
3055 }
3056
3057 PrevReg = TmpReg;
3058 Regs.push_back(TmpReg++);
3059 }
3060 }
3061
3062 RegRange = false;
3063 } else {
3064 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3065 (RegNo != Mips::RA)) {
3066 Error(E, "$16 or $31 expected");
3067 return MatchOperand_ParseFail;
3068 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3069 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3070 Error(E, "invalid register operand");
3071 return MatchOperand_ParseFail;
3072 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3073 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3074 Error(E, "consecutive register numbers expected");
3075 return MatchOperand_ParseFail;
3076 }
3077
3078 Regs.push_back(RegNo);
3079 }
3080
3081 if (Parser.getTok().is(AsmToken::Minus))
3082 RegRange = true;
3083
3084 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3085 !Parser.getTok().isNot(AsmToken::Comma)) {
3086 Error(E, "',' or '-' expected");
3087 return MatchOperand_ParseFail;
3088 }
3089
3090 Lex(); // Consume comma or minus
3091 if (Parser.getTok().isNot(AsmToken::Dollar))
3092 break;
3093
3094 PrevReg = RegNo;
3095 }
3096
3097 SMLoc E = Parser.getTok().getLoc();
3098 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3099 parseMemOperand(Operands);
3100 return MatchOperand_Success;
3101}
3102
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003103MipsAsmParser::OperandMatchResultTy
3104MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3105 MCAsmParser &Parser = getParser();
3106
3107 SMLoc S = Parser.getTok().getLoc();
3108 if (parseAnyRegister(Operands) != MatchOperand_Success)
3109 return MatchOperand_ParseFail;
3110
3111 SMLoc E = Parser.getTok().getLoc();
3112 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3113 unsigned Reg = Op.getGPR32Reg();
3114 Operands.pop_back();
3115 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3116 return MatchOperand_Success;
3117}
3118
Zoran Jovanovic41688672015-02-10 16:36:20 +00003119MipsAsmParser::OperandMatchResultTy
3120MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3121 MCAsmParser &Parser = getParser();
3122 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3123 SmallVector<unsigned, 10> Regs;
3124
3125 if (Parser.getTok().isNot(AsmToken::Dollar))
3126 return MatchOperand_ParseFail;
3127
3128 SMLoc S = Parser.getTok().getLoc();
3129
3130 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3131 return MatchOperand_ParseFail;
3132
3133 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3134 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3135 Regs.push_back(RegNo);
3136
3137 SMLoc E = Parser.getTok().getLoc();
3138 if (Parser.getTok().isNot(AsmToken::Comma)) {
3139 Error(E, "',' expected");
3140 return MatchOperand_ParseFail;
3141 }
3142
3143 // Remove comma.
3144 Parser.Lex();
3145
3146 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3147 return MatchOperand_ParseFail;
3148
3149 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3150 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3151 Regs.push_back(RegNo);
3152
3153 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3154
3155 return MatchOperand_Success;
3156}
3157
Jack Carterdc1e35d2012-09-06 20:00:02 +00003158MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3159
Vladimir Medic4c299852013-11-06 11:27:05 +00003160 MCSymbolRefExpr::VariantKind VK =
3161 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3162 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3163 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3164 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3165 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3166 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3167 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3168 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3169 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3170 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3171 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3172 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3173 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3174 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3175 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3176 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3177 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3178 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003179 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3180 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3181 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3182 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3183 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3184 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003185 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3186 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003187 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003188
Matheus Almeida2852af82014-04-22 10:15:54 +00003189 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003190
Jack Carterdc1e35d2012-09-06 20:00:02 +00003191 return VK;
3192}
Jack Cartera63b16a2012-09-07 00:23:42 +00003193
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003194/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3195/// either this.
3196/// ::= '(', register, ')'
3197/// handle it before we iterate so we don't get tripped up by the lack of
3198/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003199bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003200 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003201 if (getLexer().is(AsmToken::LParen)) {
3202 Operands.push_back(
3203 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3204 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003205 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003206 SMLoc Loc = getLexer().getLoc();
3207 Parser.eatToEndOfStatement();
3208 return Error(Loc, "unexpected token in argument list");
3209 }
3210 if (Parser.getTok().isNot(AsmToken::RParen)) {
3211 SMLoc Loc = getLexer().getLoc();
3212 Parser.eatToEndOfStatement();
3213 return Error(Loc, "unexpected token, expected ')'");
3214 }
3215 Operands.push_back(
3216 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3217 Parser.Lex();
3218 }
3219 return false;
3220}
3221
3222/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3223/// either one of these.
3224/// ::= '[', register, ']'
3225/// ::= '[', integer, ']'
3226/// handle it before we iterate so we don't get tripped up by the lack of
3227/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003228bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003229 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003230 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003231 if (getLexer().is(AsmToken::LBrac)) {
3232 Operands.push_back(
3233 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3234 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003235 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003236 SMLoc Loc = getLexer().getLoc();
3237 Parser.eatToEndOfStatement();
3238 return Error(Loc, "unexpected token in argument list");
3239 }
3240 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3241 SMLoc Loc = getLexer().getLoc();
3242 Parser.eatToEndOfStatement();
3243 return Error(Loc, "unexpected token, expected ']'");
3244 }
3245 Operands.push_back(
3246 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3247 Parser.Lex();
3248 }
3249 return false;
3250}
3251
David Blaikie960ea3f2014-06-08 16:18:35 +00003252bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3253 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003254 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003255 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003256
3257 // We have reached first instruction, module directive are now forbidden.
3258 getTargetStreamer().forbidModuleDirective();
3259
Vladimir Medic74593e62013-07-17 15:00:42 +00003260 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003261 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003262 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003263 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003264 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003265 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003266 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003267
3268 // Read the remaining operands.
3269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3270 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003271 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003272 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003273 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003274 return Error(Loc, "unexpected token in argument list");
3275 }
Toma Tabacu13964452014-09-04 13:23:44 +00003276 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003277 return true;
3278 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003279
Jack Carterd0bd6422013-04-18 00:41:53 +00003280 while (getLexer().is(AsmToken::Comma)) {
3281 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003282 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003283 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003284 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003285 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003286 return Error(Loc, "unexpected token in argument list");
3287 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003288 // Parse bracket and parenthesis suffixes before we iterate
3289 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003290 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003291 return true;
3292 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003293 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003294 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003295 }
3296 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3298 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 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003302 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003303 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003304}
3305
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003306bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003307 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003308 SMLoc Loc = getLexer().getLoc();
3309 Parser.eatToEndOfStatement();
3310 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003311}
3312
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003313bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003314 return Error(Loc, ErrorMsg);
3315}
3316
Jack Carter0b744b32012-10-04 02:29:46 +00003317bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003318 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003319 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003320
3321 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003322 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003323
3324 Parser.Lex(); // Eat "noat".
3325
Jack Carterd0bd6422013-04-18 00:41:53 +00003326 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003327 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003328 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003329 return false;
3330 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003331
3332 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003333 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003334 return false;
3335}
Jack Carterd0bd6422013-04-18 00:41:53 +00003336
Jack Carter0b744b32012-10-04 02:29:46 +00003337bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003338 // Line can be: ".set at", which sets $at to $1
3339 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003340 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003341 Parser.Lex(); // Eat "at".
3342
Jack Carter0b744b32012-10-04 02:29:46 +00003343 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003344 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003345 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003346
3347 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003348 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003349 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003350 }
3351
3352 if (getLexer().isNot(AsmToken::Equal)) {
3353 reportParseError("unexpected token, expected equals sign");
3354 return false;
3355 }
3356 Parser.Lex(); // Eat "=".
3357
3358 if (getLexer().isNot(AsmToken::Dollar)) {
3359 if (getLexer().is(AsmToken::EndOfStatement)) {
3360 reportParseError("no register specified");
3361 return false;
3362 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003363 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003364 return false;
3365 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003366 }
3367 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003368
Toma Tabacu16a74492015-02-13 10:30:57 +00003369 // Find out what "reg" is.
3370 unsigned AtRegNo;
3371 const AsmToken &Reg = Parser.getTok();
3372 if (Reg.is(AsmToken::Identifier)) {
3373 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3374 } else if (Reg.is(AsmToken::Integer)) {
3375 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003376 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003377 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003378 return false;
3379 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003380
3381 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003382 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003383 reportParseError("invalid register");
3384 return false;
3385 }
3386 Parser.Lex(); // Eat "reg".
3387
3388 // If this is not the end of the statement, report an error.
3389 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3390 reportParseError("unexpected token, expected end of statement");
3391 return false;
3392 }
3393
3394 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3395
3396 Parser.Lex(); // Consume the EndOfStatement.
3397 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003398}
3399
3400bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003401 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003402 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003403 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003404 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003405 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003406 return false;
3407 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003408 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003409 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003410 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003411 return false;
3412}
3413
3414bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003415 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003416 Parser.Lex();
3417 // If this is not the end of the statement, report an error.
3418 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003419 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003420 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003421 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003422 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003423 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003424 Parser.Lex(); // Consume the EndOfStatement.
3425 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003426}
3427
3428bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003429 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003430 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003431 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003432 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003433 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003434 return false;
3435 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003436 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003437 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003438 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003439 return false;
3440}
3441
3442bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003443 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003444 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003445 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003446 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003447 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003448 return false;
3449 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003450 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003451 reportParseError("`noreorder' must be set before `nomacro'");
3452 return false;
3453 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003454 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003455 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003456 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003457 return false;
3458}
Jack Carterd76b2372013-03-21 21:44:16 +00003459
Daniel Sanders44934432014-08-07 12:03:36 +00003460bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003461 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003462 Parser.Lex();
3463
3464 // If this is not the end of the statement, report an error.
3465 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003466 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003467
3468 setFeatureBits(Mips::FeatureMSA, "msa");
3469 getTargetStreamer().emitDirectiveSetMsa();
3470 return false;
3471}
3472
3473bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003474 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003475 Parser.Lex();
3476
3477 // If this is not the end of the statement, report an error.
3478 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003479 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003480
3481 clearFeatureBits(Mips::FeatureMSA, "msa");
3482 getTargetStreamer().emitDirectiveSetNoMsa();
3483 return false;
3484}
3485
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003486bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003487 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003488 Parser.Lex(); // Eat "nodsp".
3489
3490 // If this is not the end of the statement, report an error.
3491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3492 reportParseError("unexpected token, expected end of statement");
3493 return false;
3494 }
3495
3496 clearFeatureBits(Mips::FeatureDSP, "dsp");
3497 getTargetStreamer().emitDirectiveSetNoDsp();
3498 return false;
3499}
3500
Toma Tabacucc2502d2014-11-04 17:18:07 +00003501bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003502 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003503 Parser.Lex(); // Eat "mips16".
3504
Jack Carter39536722014-01-22 23:08:42 +00003505 // If this is not the end of the statement, report an error.
3506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003507 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003508 return false;
3509 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003510
3511 setFeatureBits(Mips::FeatureMips16, "mips16");
3512 getTargetStreamer().emitDirectiveSetMips16();
3513 Parser.Lex(); // Consume the EndOfStatement.
3514 return false;
3515}
3516
3517bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003518 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003519 Parser.Lex(); // Eat "nomips16".
3520
3521 // If this is not the end of the statement, report an error.
3522 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3523 reportParseError("unexpected token, expected end of statement");
3524 return false;
3525 }
3526
3527 clearFeatureBits(Mips::FeatureMips16, "mips16");
3528 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003529 Parser.Lex(); // Consume the EndOfStatement.
3530 return false;
3531}
3532
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003533bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003534 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003535 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003536 // Line can be: .set fp=32
3537 // .set fp=xx
3538 // .set fp=64
3539 Parser.Lex(); // Eat fp token
3540 AsmToken Tok = Parser.getTok();
3541 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003542 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003543 return false;
3544 }
3545 Parser.Lex(); // Eat '=' token.
3546 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003547
3548 if (!parseFpABIValue(FpAbiVal, ".set"))
3549 return false;
3550
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003551 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003552 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003553 return false;
3554 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003555 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003556 Parser.Lex(); // Consume the EndOfStatement.
3557 return false;
3558}
3559
Toma Tabacu9db22db2014-09-09 10:15:38 +00003560bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003561 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003562 SMLoc Loc = getLexer().getLoc();
3563
3564 Parser.Lex();
3565 if (getLexer().isNot(AsmToken::EndOfStatement))
3566 return reportParseError("unexpected token, expected end of statement");
3567
3568 // Always keep an element on the options "stack" to prevent the user
3569 // from changing the initial options. This is how we remember them.
3570 if (AssemblerOptions.size() == 2)
3571 return reportParseError(Loc, ".set pop with no .set push");
3572
3573 AssemblerOptions.pop_back();
3574 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3575
3576 getTargetStreamer().emitDirectiveSetPop();
3577 return false;
3578}
3579
3580bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003581 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003582 Parser.Lex();
3583 if (getLexer().isNot(AsmToken::EndOfStatement))
3584 return reportParseError("unexpected token, expected end of statement");
3585
3586 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003587 AssemblerOptions.push_back(
3588 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003589
3590 getTargetStreamer().emitDirectiveSetPush();
3591 return false;
3592}
3593
Jack Carterd76b2372013-03-21 21:44:16 +00003594bool MipsAsmParser::parseSetAssignment() {
3595 StringRef Name;
3596 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003597 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003598
3599 if (Parser.parseIdentifier(Name))
3600 reportParseError("expected identifier after .set");
3601
3602 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003603 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003604 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003605
Jack Carter3b2c96e2014-01-22 23:31:38 +00003606 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003607 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003608
Toma Tabacuf25949b2015-04-07 13:59:39 +00003609 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003610 Sym->setVariableValue(Value);
3611
3612 return false;
3613}
Jack Carterd0bd6422013-04-18 00:41:53 +00003614
Toma Tabacu26647792014-09-09 12:52:14 +00003615bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003616 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003617 Parser.Lex();
3618 if (getLexer().isNot(AsmToken::EndOfStatement))
3619 return reportParseError("unexpected token, expected end of statement");
3620
3621 // Reset assembler options to their initial values.
3622 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3623 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3624
3625 getTargetStreamer().emitDirectiveSetMips0();
3626 return false;
3627}
3628
Toma Tabacu85618b32014-08-19 14:22:52 +00003629bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003630 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003631 Parser.Lex();
3632 if (getLexer().isNot(AsmToken::Equal))
3633 return reportParseError("unexpected token, expected equals sign");
3634
3635 Parser.Lex();
3636 StringRef Arch;
3637 if (Parser.parseIdentifier(Arch))
3638 return reportParseError("expected arch identifier");
3639
3640 StringRef ArchFeatureName =
3641 StringSwitch<StringRef>(Arch)
3642 .Case("mips1", "mips1")
3643 .Case("mips2", "mips2")
3644 .Case("mips3", "mips3")
3645 .Case("mips4", "mips4")
3646 .Case("mips5", "mips5")
3647 .Case("mips32", "mips32")
3648 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003649 .Case("mips32r3", "mips32r3")
3650 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003651 .Case("mips32r6", "mips32r6")
3652 .Case("mips64", "mips64")
3653 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003654 .Case("mips64r3", "mips64r3")
3655 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003656 .Case("mips64r6", "mips64r6")
3657 .Case("cnmips", "cnmips")
3658 .Case("r4000", "mips3") // This is an implementation of Mips3.
3659 .Default("");
3660
3661 if (ArchFeatureName.empty())
3662 return reportParseError("unsupported architecture");
3663
3664 selectArch(ArchFeatureName);
3665 getTargetStreamer().emitDirectiveSetArch(Arch);
3666 return false;
3667}
3668
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003669bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003670 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003671 Parser.Lex();
3672 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003673 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003674
Matheus Almeida2852af82014-04-22 10:15:54 +00003675 switch (Feature) {
3676 default:
3677 llvm_unreachable("Unimplemented feature");
3678 case Mips::FeatureDSP:
3679 setFeatureBits(Mips::FeatureDSP, "dsp");
3680 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003681 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003682 case Mips::FeatureMicroMips:
3683 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003684 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003685 case Mips::FeatureMips1:
3686 selectArch("mips1");
3687 getTargetStreamer().emitDirectiveSetMips1();
3688 break;
3689 case Mips::FeatureMips2:
3690 selectArch("mips2");
3691 getTargetStreamer().emitDirectiveSetMips2();
3692 break;
3693 case Mips::FeatureMips3:
3694 selectArch("mips3");
3695 getTargetStreamer().emitDirectiveSetMips3();
3696 break;
3697 case Mips::FeatureMips4:
3698 selectArch("mips4");
3699 getTargetStreamer().emitDirectiveSetMips4();
3700 break;
3701 case Mips::FeatureMips5:
3702 selectArch("mips5");
3703 getTargetStreamer().emitDirectiveSetMips5();
3704 break;
3705 case Mips::FeatureMips32:
3706 selectArch("mips32");
3707 getTargetStreamer().emitDirectiveSetMips32();
3708 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003709 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003710 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003711 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003712 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003713 case Mips::FeatureMips32r3:
3714 selectArch("mips32r3");
3715 getTargetStreamer().emitDirectiveSetMips32R3();
3716 break;
3717 case Mips::FeatureMips32r5:
3718 selectArch("mips32r5");
3719 getTargetStreamer().emitDirectiveSetMips32R5();
3720 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003721 case Mips::FeatureMips32r6:
3722 selectArch("mips32r6");
3723 getTargetStreamer().emitDirectiveSetMips32R6();
3724 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003725 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003726 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003727 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003728 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003729 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003730 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003731 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003732 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003733 case Mips::FeatureMips64r3:
3734 selectArch("mips64r3");
3735 getTargetStreamer().emitDirectiveSetMips64R3();
3736 break;
3737 case Mips::FeatureMips64r5:
3738 selectArch("mips64r5");
3739 getTargetStreamer().emitDirectiveSetMips64R5();
3740 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003741 case Mips::FeatureMips64r6:
3742 selectArch("mips64r6");
3743 getTargetStreamer().emitDirectiveSetMips64R6();
3744 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003745 }
3746 return false;
3747}
3748
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003749bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003750 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003751 if (getLexer().isNot(AsmToken::Comma)) {
3752 SMLoc Loc = getLexer().getLoc();
3753 Parser.eatToEndOfStatement();
3754 return Error(Loc, ErrorStr);
3755 }
3756
Matheus Almeida2852af82014-04-22 10:15:54 +00003757 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003758 return true;
3759}
3760
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003761bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003762 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003763 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003764
Toma Tabacudde4c462014-11-06 10:02:45 +00003765 if (inMips16Mode()) {
3766 reportParseError(".cpload is not supported in Mips16 mode");
3767 return false;
3768 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003769
David Blaikie960ea3f2014-06-08 16:18:35 +00003770 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003771 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003772 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3773 reportParseError("expected register containing function address");
3774 return false;
3775 }
3776
David Blaikie960ea3f2014-06-08 16:18:35 +00003777 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3778 if (!RegOpnd.isGPRAsmReg()) {
3779 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003780 return false;
3781 }
3782
Toma Tabacudde4c462014-11-06 10:02:45 +00003783 // If this is not the end of the statement, report an error.
3784 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3785 reportParseError("unexpected token, expected end of statement");
3786 return false;
3787 }
3788
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003789 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003790 return false;
3791}
3792
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003793bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003794 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003795 unsigned FuncReg;
3796 unsigned Save;
3797 bool SaveIsReg = true;
3798
Matheus Almeida7e815762014-06-18 13:08:59 +00003799 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003800 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003801 if (ResTy == MatchOperand_NoMatch) {
3802 reportParseError("expected register containing function address");
3803 Parser.eatToEndOfStatement();
3804 return false;
3805 }
3806
3807 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3808 if (!FuncRegOpnd.isGPRAsmReg()) {
3809 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3810 Parser.eatToEndOfStatement();
3811 return false;
3812 }
3813
3814 FuncReg = FuncRegOpnd.getGPR32Reg();
3815 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003816
Toma Tabacu65f10572014-09-16 15:00:52 +00003817 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003818 return true;
3819
Toma Tabacu13964452014-09-04 13:23:44 +00003820 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003821 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003822 const AsmToken &Tok = Parser.getTok();
3823 if (Tok.is(AsmToken::Integer)) {
3824 Save = Tok.getIntVal();
3825 SaveIsReg = false;
3826 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003827 } else {
3828 reportParseError("expected save register or stack offset");
3829 Parser.eatToEndOfStatement();
3830 return false;
3831 }
3832 } else {
3833 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3834 if (!SaveOpnd.isGPRAsmReg()) {
3835 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3836 Parser.eatToEndOfStatement();
3837 return false;
3838 }
3839 Save = SaveOpnd.getGPR32Reg();
3840 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003841
Toma Tabacu65f10572014-09-16 15:00:52 +00003842 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003843 return true;
3844
Toma Tabacu8874eac2015-02-18 13:46:53 +00003845 const MCExpr *Expr;
3846 if (Parser.parseExpression(Expr)) {
3847 reportParseError("expected expression");
3848 return false;
3849 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003850
Toma Tabacu8874eac2015-02-18 13:46:53 +00003851 if (Expr->getKind() != MCExpr::SymbolRef) {
3852 reportParseError("expected symbol");
3853 return false;
3854 }
3855 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3856
3857 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3858 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003859 return false;
3860}
3861
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003862bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003863 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003864 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3865 const AsmToken &Tok = Parser.getTok();
3866
3867 if (Tok.getString() == "2008") {
3868 Parser.Lex();
3869 getTargetStreamer().emitDirectiveNaN2008();
3870 return false;
3871 } else if (Tok.getString() == "legacy") {
3872 Parser.Lex();
3873 getTargetStreamer().emitDirectiveNaNLegacy();
3874 return false;
3875 }
3876 }
3877 // If we don't recognize the option passed to the .nan
3878 // directive (e.g. no option or unknown option), emit an error.
3879 reportParseError("invalid option in .nan directive");
3880 return false;
3881}
3882
Jack Carter0b744b32012-10-04 02:29:46 +00003883bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003884 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003885 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003886 const AsmToken &Tok = Parser.getTok();
3887
3888 if (Tok.getString() == "noat") {
3889 return parseSetNoAtDirective();
3890 } else if (Tok.getString() == "at") {
3891 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003892 } else if (Tok.getString() == "arch") {
3893 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003894 } else if (Tok.getString() == "fp") {
3895 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003896 } else if (Tok.getString() == "pop") {
3897 return parseSetPopDirective();
3898 } else if (Tok.getString() == "push") {
3899 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003900 } else if (Tok.getString() == "reorder") {
3901 return parseSetReorderDirective();
3902 } else if (Tok.getString() == "noreorder") {
3903 return parseSetNoReorderDirective();
3904 } else if (Tok.getString() == "macro") {
3905 return parseSetMacroDirective();
3906 } else if (Tok.getString() == "nomacro") {
3907 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003908 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003909 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003910 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003911 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003912 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003913 getTargetStreamer().emitDirectiveSetNoMicroMips();
3914 Parser.eatToEndOfStatement();
3915 return false;
3916 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003917 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003918 } else if (Tok.getString() == "mips0") {
3919 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003920 } else if (Tok.getString() == "mips1") {
3921 return parseSetFeature(Mips::FeatureMips1);
3922 } else if (Tok.getString() == "mips2") {
3923 return parseSetFeature(Mips::FeatureMips2);
3924 } else if (Tok.getString() == "mips3") {
3925 return parseSetFeature(Mips::FeatureMips3);
3926 } else if (Tok.getString() == "mips4") {
3927 return parseSetFeature(Mips::FeatureMips4);
3928 } else if (Tok.getString() == "mips5") {
3929 return parseSetFeature(Mips::FeatureMips5);
3930 } else if (Tok.getString() == "mips32") {
3931 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003932 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003933 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003934 } else if (Tok.getString() == "mips32r3") {
3935 return parseSetFeature(Mips::FeatureMips32r3);
3936 } else if (Tok.getString() == "mips32r5") {
3937 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003938 } else if (Tok.getString() == "mips32r6") {
3939 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003940 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003941 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003942 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003943 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003944 } else if (Tok.getString() == "mips64r3") {
3945 return parseSetFeature(Mips::FeatureMips64r3);
3946 } else if (Tok.getString() == "mips64r5") {
3947 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003948 } else if (Tok.getString() == "mips64r6") {
3949 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003950 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003951 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003952 } else if (Tok.getString() == "nodsp") {
3953 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003954 } else if (Tok.getString() == "msa") {
3955 return parseSetMsaDirective();
3956 } else if (Tok.getString() == "nomsa") {
3957 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003958 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003959 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003960 parseSetAssignment();
3961 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003962 }
Jack Carter07c818d2013-01-25 01:31:34 +00003963
Jack Carter0b744b32012-10-04 02:29:46 +00003964 return true;
3965}
3966
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003967/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003968/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003969bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003970 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3972 for (;;) {
3973 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003974 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003975 return true;
3976
3977 getParser().getStreamer().EmitValue(Value, Size);
3978
3979 if (getLexer().is(AsmToken::EndOfStatement))
3980 break;
3981
Jack Carter07c818d2013-01-25 01:31:34 +00003982 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003983 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003984 Parser.Lex();
3985 }
3986 }
3987
3988 Parser.Lex();
3989 return false;
3990}
3991
Vladimir Medic4c299852013-11-06 11:27:05 +00003992/// parseDirectiveGpWord
3993/// ::= .gpword local_sym
3994bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003995 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003996 const MCExpr *Value;
3997 // EmitGPRel32Value requires an expression, so we are using base class
3998 // method to evaluate the expression.
3999 if (getParser().parseExpression(Value))
4000 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004001 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004002
Vladimir Medice10c1122013-11-13 13:18:04 +00004003 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004004 return Error(getLexer().getLoc(),
4005 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004006 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004007 return false;
4008}
4009
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004010/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004011/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004012bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004013 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004014 const MCExpr *Value;
4015 // EmitGPRel64Value requires an expression, so we are using base class
4016 // method to evaluate the expression.
4017 if (getParser().parseExpression(Value))
4018 return true;
4019 getParser().getStreamer().EmitGPRel64Value(Value);
4020
4021 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004022 return Error(getLexer().getLoc(),
4023 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004024 Parser.Lex(); // Eat EndOfStatement token.
4025 return false;
4026}
4027
Jack Carter0cd3c192014-01-06 23:27:31 +00004028bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004029 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004030 // Get the option token.
4031 AsmToken Tok = Parser.getTok();
4032 // At the moment only identifiers are supported.
4033 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004034 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004035 Parser.eatToEndOfStatement();
4036 return false;
4037 }
4038
4039 StringRef Option = Tok.getIdentifier();
4040
4041 if (Option == "pic0") {
4042 getTargetStreamer().emitDirectiveOptionPic0();
4043 Parser.Lex();
4044 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4045 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004046 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004047 Parser.eatToEndOfStatement();
4048 }
4049 return false;
4050 }
4051
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004052 if (Option == "pic2") {
4053 getTargetStreamer().emitDirectiveOptionPic2();
4054 Parser.Lex();
4055 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4056 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004057 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004058 Parser.eatToEndOfStatement();
4059 }
4060 return false;
4061 }
4062
Jack Carter0cd3c192014-01-06 23:27:31 +00004063 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004064 Warning(Parser.getTok().getLoc(),
4065 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004066 Parser.eatToEndOfStatement();
4067 return false;
4068}
4069
Toma Tabacu9ca50962015-04-16 09:53:47 +00004070/// parseInsnDirective
4071/// ::= .insn
4072bool MipsAsmParser::parseInsnDirective() {
4073 // If this is not the end of the statement, report an error.
4074 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4075 reportParseError("unexpected token, expected end of statement");
4076 return false;
4077 }
4078
4079 // The actual label marking happens in
4080 // MipsELFStreamer::createPendingLabelRelocs().
4081 getTargetStreamer().emitDirectiveInsn();
4082
4083 getParser().Lex(); // Eat EndOfStatement token.
4084 return false;
4085}
4086
Daniel Sanders7e527422014-07-10 13:38:23 +00004087/// parseDirectiveModule
4088/// ::= .module oddspreg
4089/// ::= .module nooddspreg
4090/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004091bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004092 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004093 MCAsmLexer &Lexer = getLexer();
4094 SMLoc L = Lexer.getLoc();
4095
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004096 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004097 // TODO : get a better message.
4098 reportParseError(".module directive must appear before any code");
4099 return false;
4100 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004101
Toma Tabacuc405c822015-01-23 10:40:19 +00004102 StringRef Option;
4103 if (Parser.parseIdentifier(Option)) {
4104 reportParseError("expected .module option identifier");
4105 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004106 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004107
Toma Tabacuc405c822015-01-23 10:40:19 +00004108 if (Option == "oddspreg") {
4109 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4110 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4111
4112 // If this is not the end of the statement, report an error.
4113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4114 reportParseError("unexpected token, expected end of statement");
4115 return false;
4116 }
4117
4118 return false; // parseDirectiveModule has finished successfully.
4119 } else if (Option == "nooddspreg") {
4120 if (!isABI_O32()) {
4121 Error(L, "'.module nooddspreg' requires the O32 ABI");
4122 return false;
4123 }
4124
4125 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4126 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4127
4128 // If this is not the end of the statement, report an error.
4129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4130 reportParseError("unexpected token, expected end of statement");
4131 return false;
4132 }
4133
4134 return false; // parseDirectiveModule has finished successfully.
4135 } else if (Option == "fp") {
4136 return parseDirectiveModuleFP();
4137 } else {
4138 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4139 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004140}
4141
4142/// parseDirectiveModuleFP
4143/// ::= =32
4144/// ::= =xx
4145/// ::= =64
4146bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004147 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004148 MCAsmLexer &Lexer = getLexer();
4149
4150 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004151 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004152 return false;
4153 }
4154 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004155
Daniel Sanders7e527422014-07-10 13:38:23 +00004156 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004157 if (!parseFpABIValue(FpABI, ".module"))
4158 return false;
4159
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004160 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004161 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004162 return false;
4163 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004164
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004165 // Emit appropriate flags.
4166 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004167 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004168 return false;
4169}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004170
Daniel Sanders7e527422014-07-10 13:38:23 +00004171bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004172 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004173 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004174 MCAsmLexer &Lexer = getLexer();
4175
4176 if (Lexer.is(AsmToken::Identifier)) {
4177 StringRef Value = Parser.getTok().getString();
4178 Parser.Lex();
4179
4180 if (Value != "xx") {
4181 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4182 return false;
4183 }
4184
4185 if (!isABI_O32()) {
4186 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4187 return false;
4188 }
4189
Daniel Sanders7e527422014-07-10 13:38:23 +00004190 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004191 return true;
4192 }
4193
4194 if (Lexer.is(AsmToken::Integer)) {
4195 unsigned Value = Parser.getTok().getIntVal();
4196 Parser.Lex();
4197
4198 if (Value != 32 && Value != 64) {
4199 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4200 return false;
4201 }
4202
4203 if (Value == 32) {
4204 if (!isABI_O32()) {
4205 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4206 return false;
4207 }
4208
Daniel Sanders7e527422014-07-10 13:38:23 +00004209 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4210 } else
4211 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004212
Daniel Sanders7e527422014-07-10 13:38:23 +00004213 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004214 }
4215
4216 return false;
4217}
4218
Jack Carter0b744b32012-10-04 02:29:46 +00004219bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004220 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004221 StringRef IDVal = DirectiveID.getString();
4222
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004223 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004224 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004225 if (IDVal == ".dword") {
4226 parseDataDirective(8, DirectiveID.getLoc());
4227 return false;
4228 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004229 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004230 StringRef SymbolName;
4231
4232 if (Parser.parseIdentifier(SymbolName)) {
4233 reportParseError("expected identifier after .ent");
4234 return false;
4235 }
4236
4237 // There's an undocumented extension that allows an integer to
4238 // follow the name of the procedure which AFAICS is ignored by GAS.
4239 // Example: .ent foo,2
4240 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4241 if (getLexer().isNot(AsmToken::Comma)) {
4242 // Even though we accept this undocumented extension for compatibility
4243 // reasons, the additional integer argument does not actually change
4244 // the behaviour of the '.ent' directive, so we would like to discourage
4245 // its use. We do this by not referring to the extended version in
4246 // error messages which are not directly related to its use.
4247 reportParseError("unexpected token, expected end of statement");
4248 return false;
4249 }
4250 Parser.Lex(); // Eat the comma.
4251 const MCExpr *DummyNumber;
4252 int64_t DummyNumberVal;
4253 // If the user was explicitly trying to use the extended version,
4254 // we still give helpful extension-related error messages.
4255 if (Parser.parseExpression(DummyNumber)) {
4256 reportParseError("expected number after comma");
4257 return false;
4258 }
4259 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4260 reportParseError("expected an absolute expression after comma");
4261 return false;
4262 }
4263 }
4264
4265 // If this is not the end of the statement, report an error.
4266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4267 reportParseError("unexpected token, expected end of statement");
4268 return false;
4269 }
4270
4271 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4272
4273 getTargetStreamer().emitDirectiveEnt(*Sym);
4274 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004275 return false;
4276 }
4277
Jack Carter07c818d2013-01-25 01:31:34 +00004278 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004279 StringRef SymbolName;
4280
4281 if (Parser.parseIdentifier(SymbolName)) {
4282 reportParseError("expected identifier after .end");
4283 return false;
4284 }
4285
4286 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4287 reportParseError("unexpected token, expected end of statement");
4288 return false;
4289 }
4290
4291 if (CurrentFn == nullptr) {
4292 reportParseError(".end used without .ent");
4293 return false;
4294 }
4295
4296 if ((SymbolName != CurrentFn->getName())) {
4297 reportParseError(".end symbol does not match .ent symbol");
4298 return false;
4299 }
4300
4301 getTargetStreamer().emitDirectiveEnd(SymbolName);
4302 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004303 return false;
4304 }
4305
Jack Carter07c818d2013-01-25 01:31:34 +00004306 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004307 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4308 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004309 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004310 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4311 reportParseError("expected stack register");
4312 return false;
4313 }
4314
4315 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4316 if (!StackRegOpnd.isGPRAsmReg()) {
4317 reportParseError(StackRegOpnd.getStartLoc(),
4318 "expected general purpose register");
4319 return false;
4320 }
4321 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4322
4323 if (Parser.getTok().is(AsmToken::Comma))
4324 Parser.Lex();
4325 else {
4326 reportParseError("unexpected token, expected comma");
4327 return false;
4328 }
4329
4330 // Parse the frame size.
4331 const MCExpr *FrameSize;
4332 int64_t FrameSizeVal;
4333
4334 if (Parser.parseExpression(FrameSize)) {
4335 reportParseError("expected frame size value");
4336 return false;
4337 }
4338
4339 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4340 reportParseError("frame size not an absolute expression");
4341 return false;
4342 }
4343
4344 if (Parser.getTok().is(AsmToken::Comma))
4345 Parser.Lex();
4346 else {
4347 reportParseError("unexpected token, expected comma");
4348 return false;
4349 }
4350
4351 // Parse the return register.
4352 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004353 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004354 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4355 reportParseError("expected return register");
4356 return false;
4357 }
4358
4359 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4360 if (!ReturnRegOpnd.isGPRAsmReg()) {
4361 reportParseError(ReturnRegOpnd.getStartLoc(),
4362 "expected general purpose register");
4363 return false;
4364 }
4365
4366 // If this is not the end of the statement, report an error.
4367 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4368 reportParseError("unexpected token, expected end of statement");
4369 return false;
4370 }
4371
4372 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4373 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004374 return false;
4375 }
4376
Jack Carter07c818d2013-01-25 01:31:34 +00004377 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004378 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004379 }
4380
Daniel Sandersd97a6342014-08-13 10:07:34 +00004381 if (IDVal == ".mask" || IDVal == ".fmask") {
4382 // .mask bitmask, frame_offset
4383 // bitmask: One bit for each register used.
4384 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4385 // first register is expected to be saved.
4386 // Examples:
4387 // .mask 0x80000000, -4
4388 // .fmask 0x80000000, -4
4389 //
Jack Carterbe332172012-09-07 00:48:02 +00004390
Daniel Sandersd97a6342014-08-13 10:07:34 +00004391 // Parse the bitmask
4392 const MCExpr *BitMask;
4393 int64_t BitMaskVal;
4394
4395 if (Parser.parseExpression(BitMask)) {
4396 reportParseError("expected bitmask value");
4397 return false;
4398 }
4399
4400 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4401 reportParseError("bitmask not an absolute expression");
4402 return false;
4403 }
4404
4405 if (Parser.getTok().is(AsmToken::Comma))
4406 Parser.Lex();
4407 else {
4408 reportParseError("unexpected token, expected comma");
4409 return false;
4410 }
4411
4412 // Parse the frame_offset
4413 const MCExpr *FrameOffset;
4414 int64_t FrameOffsetVal;
4415
4416 if (Parser.parseExpression(FrameOffset)) {
4417 reportParseError("expected frame offset value");
4418 return false;
4419 }
4420
4421 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4422 reportParseError("frame offset not an absolute expression");
4423 return false;
4424 }
4425
4426 // If this is not the end of the statement, report an error.
4427 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4428 reportParseError("unexpected token, expected end of statement");
4429 return false;
4430 }
4431
4432 if (IDVal == ".mask")
4433 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4434 else
4435 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004436 return false;
4437 }
4438
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004439 if (IDVal == ".nan")
4440 return parseDirectiveNaN();
4441
Jack Carter07c818d2013-01-25 01:31:34 +00004442 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004443 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004444 return false;
4445 }
4446
Rafael Espindolab59fb732014-03-28 18:50:26 +00004447 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004448 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004449 return false;
4450 }
4451
Jack Carter07c818d2013-01-25 01:31:34 +00004452 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004453 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004454 return false;
4455 }
4456
Jack Carter0cd3c192014-01-06 23:27:31 +00004457 if (IDVal == ".option")
4458 return parseDirectiveOption();
4459
4460 if (IDVal == ".abicalls") {
4461 getTargetStreamer().emitDirectiveAbiCalls();
4462 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004463 Error(Parser.getTok().getLoc(),
4464 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004465 // Clear line
4466 Parser.eatToEndOfStatement();
4467 }
4468 return false;
4469 }
4470
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004471 if (IDVal == ".cpsetup")
4472 return parseDirectiveCPSetup();
4473
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004474 if (IDVal == ".module")
4475 return parseDirectiveModule();
4476
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004477 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4478 return parseInternalDirectiveReallowModule();
4479
Toma Tabacu9ca50962015-04-16 09:53:47 +00004480 if (IDVal == ".insn")
4481 return parseInsnDirective();
4482
Rafael Espindola870c4e92012-01-11 03:56:41 +00004483 return true;
4484}
4485
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004486bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4487 // If this is not the end of the statement, report an error.
4488 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4489 reportParseError("unexpected token, expected end of statement");
4490 return false;
4491 }
4492
4493 getTargetStreamer().reallowModuleDirective();
4494
4495 getParser().Lex(); // Eat EndOfStatement token.
4496 return false;
4497}
4498
Rafael Espindola870c4e92012-01-11 03:56:41 +00004499extern "C" void LLVMInitializeMipsAsmParser() {
4500 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4501 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4502 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4503 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4504}
Jack Carterb4dbc172012-09-05 23:34:03 +00004505
4506#define GET_REGISTER_MATCHER
4507#define GET_MATCHER_IMPLEMENTATION
4508#include "MipsGenAsmMatcher.inc"