blob: 45169b70513ba5b96f45ff5eed7db311b831d976 [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();
Jack Carterd0bd6422013-04-18 00:41:53 +00003437 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003438 return false;
3439}
3440
3441bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003442 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003443 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003444 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003445 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003446 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003447 return false;
3448 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003449 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003450 reportParseError("`noreorder' must be set before `nomacro'");
3451 return false;
3452 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003453 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003454 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003455 return false;
3456}
Jack Carterd76b2372013-03-21 21:44:16 +00003457
Daniel Sanders44934432014-08-07 12:03:36 +00003458bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003459 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003460 Parser.Lex();
3461
3462 // If this is not the end of the statement, report an error.
3463 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003464 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003465
3466 setFeatureBits(Mips::FeatureMSA, "msa");
3467 getTargetStreamer().emitDirectiveSetMsa();
3468 return false;
3469}
3470
3471bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003472 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003473 Parser.Lex();
3474
3475 // If this is not the end of the statement, report an error.
3476 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003477 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003478
3479 clearFeatureBits(Mips::FeatureMSA, "msa");
3480 getTargetStreamer().emitDirectiveSetNoMsa();
3481 return false;
3482}
3483
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003484bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003485 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003486 Parser.Lex(); // Eat "nodsp".
3487
3488 // If this is not the end of the statement, report an error.
3489 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3490 reportParseError("unexpected token, expected end of statement");
3491 return false;
3492 }
3493
3494 clearFeatureBits(Mips::FeatureDSP, "dsp");
3495 getTargetStreamer().emitDirectiveSetNoDsp();
3496 return false;
3497}
3498
Toma Tabacucc2502d2014-11-04 17:18:07 +00003499bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003500 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003501 Parser.Lex(); // Eat "mips16".
3502
Jack Carter39536722014-01-22 23:08:42 +00003503 // If this is not the end of the statement, report an error.
3504 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003505 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003506 return false;
3507 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003508
3509 setFeatureBits(Mips::FeatureMips16, "mips16");
3510 getTargetStreamer().emitDirectiveSetMips16();
3511 Parser.Lex(); // Consume the EndOfStatement.
3512 return false;
3513}
3514
3515bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003516 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003517 Parser.Lex(); // Eat "nomips16".
3518
3519 // If this is not the end of the statement, report an error.
3520 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3521 reportParseError("unexpected token, expected end of statement");
3522 return false;
3523 }
3524
3525 clearFeatureBits(Mips::FeatureMips16, "mips16");
3526 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003527 Parser.Lex(); // Consume the EndOfStatement.
3528 return false;
3529}
3530
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003531bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003532 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003533 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003534 // Line can be: .set fp=32
3535 // .set fp=xx
3536 // .set fp=64
3537 Parser.Lex(); // Eat fp token
3538 AsmToken Tok = Parser.getTok();
3539 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003540 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003541 return false;
3542 }
3543 Parser.Lex(); // Eat '=' token.
3544 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003545
3546 if (!parseFpABIValue(FpAbiVal, ".set"))
3547 return false;
3548
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003549 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003550 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003551 return false;
3552 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003553 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003554 Parser.Lex(); // Consume the EndOfStatement.
3555 return false;
3556}
3557
Toma Tabacu9db22db2014-09-09 10:15:38 +00003558bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003559 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003560 SMLoc Loc = getLexer().getLoc();
3561
3562 Parser.Lex();
3563 if (getLexer().isNot(AsmToken::EndOfStatement))
3564 return reportParseError("unexpected token, expected end of statement");
3565
3566 // Always keep an element on the options "stack" to prevent the user
3567 // from changing the initial options. This is how we remember them.
3568 if (AssemblerOptions.size() == 2)
3569 return reportParseError(Loc, ".set pop with no .set push");
3570
3571 AssemblerOptions.pop_back();
3572 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3573
3574 getTargetStreamer().emitDirectiveSetPop();
3575 return false;
3576}
3577
3578bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003579 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003580 Parser.Lex();
3581 if (getLexer().isNot(AsmToken::EndOfStatement))
3582 return reportParseError("unexpected token, expected end of statement");
3583
3584 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003585 AssemblerOptions.push_back(
3586 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003587
3588 getTargetStreamer().emitDirectiveSetPush();
3589 return false;
3590}
3591
Jack Carterd76b2372013-03-21 21:44:16 +00003592bool MipsAsmParser::parseSetAssignment() {
3593 StringRef Name;
3594 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003595 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003596
3597 if (Parser.parseIdentifier(Name))
3598 reportParseError("expected identifier after .set");
3599
3600 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003601 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003602 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003603
Jack Carter3b2c96e2014-01-22 23:31:38 +00003604 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003605 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003606
Toma Tabacuf25949b2015-04-07 13:59:39 +00003607 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003608 Sym->setVariableValue(Value);
3609
3610 return false;
3611}
Jack Carterd0bd6422013-04-18 00:41:53 +00003612
Toma Tabacu26647792014-09-09 12:52:14 +00003613bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003614 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003615 Parser.Lex();
3616 if (getLexer().isNot(AsmToken::EndOfStatement))
3617 return reportParseError("unexpected token, expected end of statement");
3618
3619 // Reset assembler options to their initial values.
3620 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3621 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3622
3623 getTargetStreamer().emitDirectiveSetMips0();
3624 return false;
3625}
3626
Toma Tabacu85618b32014-08-19 14:22:52 +00003627bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003628 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003629 Parser.Lex();
3630 if (getLexer().isNot(AsmToken::Equal))
3631 return reportParseError("unexpected token, expected equals sign");
3632
3633 Parser.Lex();
3634 StringRef Arch;
3635 if (Parser.parseIdentifier(Arch))
3636 return reportParseError("expected arch identifier");
3637
3638 StringRef ArchFeatureName =
3639 StringSwitch<StringRef>(Arch)
3640 .Case("mips1", "mips1")
3641 .Case("mips2", "mips2")
3642 .Case("mips3", "mips3")
3643 .Case("mips4", "mips4")
3644 .Case("mips5", "mips5")
3645 .Case("mips32", "mips32")
3646 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003647 .Case("mips32r3", "mips32r3")
3648 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003649 .Case("mips32r6", "mips32r6")
3650 .Case("mips64", "mips64")
3651 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003652 .Case("mips64r3", "mips64r3")
3653 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003654 .Case("mips64r6", "mips64r6")
3655 .Case("cnmips", "cnmips")
3656 .Case("r4000", "mips3") // This is an implementation of Mips3.
3657 .Default("");
3658
3659 if (ArchFeatureName.empty())
3660 return reportParseError("unsupported architecture");
3661
3662 selectArch(ArchFeatureName);
3663 getTargetStreamer().emitDirectiveSetArch(Arch);
3664 return false;
3665}
3666
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003667bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003668 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003669 Parser.Lex();
3670 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003671 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003672
Matheus Almeida2852af82014-04-22 10:15:54 +00003673 switch (Feature) {
3674 default:
3675 llvm_unreachable("Unimplemented feature");
3676 case Mips::FeatureDSP:
3677 setFeatureBits(Mips::FeatureDSP, "dsp");
3678 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003679 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003680 case Mips::FeatureMicroMips:
3681 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003682 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003683 case Mips::FeatureMips1:
3684 selectArch("mips1");
3685 getTargetStreamer().emitDirectiveSetMips1();
3686 break;
3687 case Mips::FeatureMips2:
3688 selectArch("mips2");
3689 getTargetStreamer().emitDirectiveSetMips2();
3690 break;
3691 case Mips::FeatureMips3:
3692 selectArch("mips3");
3693 getTargetStreamer().emitDirectiveSetMips3();
3694 break;
3695 case Mips::FeatureMips4:
3696 selectArch("mips4");
3697 getTargetStreamer().emitDirectiveSetMips4();
3698 break;
3699 case Mips::FeatureMips5:
3700 selectArch("mips5");
3701 getTargetStreamer().emitDirectiveSetMips5();
3702 break;
3703 case Mips::FeatureMips32:
3704 selectArch("mips32");
3705 getTargetStreamer().emitDirectiveSetMips32();
3706 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003707 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003708 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003709 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003710 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003711 case Mips::FeatureMips32r3:
3712 selectArch("mips32r3");
3713 getTargetStreamer().emitDirectiveSetMips32R3();
3714 break;
3715 case Mips::FeatureMips32r5:
3716 selectArch("mips32r5");
3717 getTargetStreamer().emitDirectiveSetMips32R5();
3718 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003719 case Mips::FeatureMips32r6:
3720 selectArch("mips32r6");
3721 getTargetStreamer().emitDirectiveSetMips32R6();
3722 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003723 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003724 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003725 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003726 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003727 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003728 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003729 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003730 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003731 case Mips::FeatureMips64r3:
3732 selectArch("mips64r3");
3733 getTargetStreamer().emitDirectiveSetMips64R3();
3734 break;
3735 case Mips::FeatureMips64r5:
3736 selectArch("mips64r5");
3737 getTargetStreamer().emitDirectiveSetMips64R5();
3738 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003739 case Mips::FeatureMips64r6:
3740 selectArch("mips64r6");
3741 getTargetStreamer().emitDirectiveSetMips64R6();
3742 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003743 }
3744 return false;
3745}
3746
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003747bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003748 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003749 if (getLexer().isNot(AsmToken::Comma)) {
3750 SMLoc Loc = getLexer().getLoc();
3751 Parser.eatToEndOfStatement();
3752 return Error(Loc, ErrorStr);
3753 }
3754
Matheus Almeida2852af82014-04-22 10:15:54 +00003755 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003756 return true;
3757}
3758
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003759bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003760 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003761 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003762
Toma Tabacudde4c462014-11-06 10:02:45 +00003763 if (inMips16Mode()) {
3764 reportParseError(".cpload is not supported in Mips16 mode");
3765 return false;
3766 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003767
David Blaikie960ea3f2014-06-08 16:18:35 +00003768 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003769 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003770 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3771 reportParseError("expected register containing function address");
3772 return false;
3773 }
3774
David Blaikie960ea3f2014-06-08 16:18:35 +00003775 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3776 if (!RegOpnd.isGPRAsmReg()) {
3777 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003778 return false;
3779 }
3780
Toma Tabacudde4c462014-11-06 10:02:45 +00003781 // If this is not the end of the statement, report an error.
3782 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3783 reportParseError("unexpected token, expected end of statement");
3784 return false;
3785 }
3786
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003787 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003788 return false;
3789}
3790
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003791bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003792 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003793 unsigned FuncReg;
3794 unsigned Save;
3795 bool SaveIsReg = true;
3796
Matheus Almeida7e815762014-06-18 13:08:59 +00003797 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003798 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003799 if (ResTy == MatchOperand_NoMatch) {
3800 reportParseError("expected register containing function address");
3801 Parser.eatToEndOfStatement();
3802 return false;
3803 }
3804
3805 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3806 if (!FuncRegOpnd.isGPRAsmReg()) {
3807 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3808 Parser.eatToEndOfStatement();
3809 return false;
3810 }
3811
3812 FuncReg = FuncRegOpnd.getGPR32Reg();
3813 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003814
Toma Tabacu65f10572014-09-16 15:00:52 +00003815 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003816 return true;
3817
Toma Tabacu13964452014-09-04 13:23:44 +00003818 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003819 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003820 const AsmToken &Tok = Parser.getTok();
3821 if (Tok.is(AsmToken::Integer)) {
3822 Save = Tok.getIntVal();
3823 SaveIsReg = false;
3824 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003825 } else {
3826 reportParseError("expected save register or stack offset");
3827 Parser.eatToEndOfStatement();
3828 return false;
3829 }
3830 } else {
3831 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3832 if (!SaveOpnd.isGPRAsmReg()) {
3833 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3834 Parser.eatToEndOfStatement();
3835 return false;
3836 }
3837 Save = SaveOpnd.getGPR32Reg();
3838 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003839
Toma Tabacu65f10572014-09-16 15:00:52 +00003840 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003841 return true;
3842
Toma Tabacu8874eac2015-02-18 13:46:53 +00003843 const MCExpr *Expr;
3844 if (Parser.parseExpression(Expr)) {
3845 reportParseError("expected expression");
3846 return false;
3847 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003848
Toma Tabacu8874eac2015-02-18 13:46:53 +00003849 if (Expr->getKind() != MCExpr::SymbolRef) {
3850 reportParseError("expected symbol");
3851 return false;
3852 }
3853 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3854
3855 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3856 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003857 return false;
3858}
3859
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003860bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003861 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003862 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3863 const AsmToken &Tok = Parser.getTok();
3864
3865 if (Tok.getString() == "2008") {
3866 Parser.Lex();
3867 getTargetStreamer().emitDirectiveNaN2008();
3868 return false;
3869 } else if (Tok.getString() == "legacy") {
3870 Parser.Lex();
3871 getTargetStreamer().emitDirectiveNaNLegacy();
3872 return false;
3873 }
3874 }
3875 // If we don't recognize the option passed to the .nan
3876 // directive (e.g. no option or unknown option), emit an error.
3877 reportParseError("invalid option in .nan directive");
3878 return false;
3879}
3880
Jack Carter0b744b32012-10-04 02:29:46 +00003881bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003882 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003883 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003884 const AsmToken &Tok = Parser.getTok();
3885
3886 if (Tok.getString() == "noat") {
3887 return parseSetNoAtDirective();
3888 } else if (Tok.getString() == "at") {
3889 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003890 } else if (Tok.getString() == "arch") {
3891 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003892 } else if (Tok.getString() == "fp") {
3893 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003894 } else if (Tok.getString() == "pop") {
3895 return parseSetPopDirective();
3896 } else if (Tok.getString() == "push") {
3897 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003898 } else if (Tok.getString() == "reorder") {
3899 return parseSetReorderDirective();
3900 } else if (Tok.getString() == "noreorder") {
3901 return parseSetNoReorderDirective();
3902 } else if (Tok.getString() == "macro") {
3903 return parseSetMacroDirective();
3904 } else if (Tok.getString() == "nomacro") {
3905 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003906 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003907 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003908 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003909 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003910 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003911 getTargetStreamer().emitDirectiveSetNoMicroMips();
3912 Parser.eatToEndOfStatement();
3913 return false;
3914 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003915 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003916 } else if (Tok.getString() == "mips0") {
3917 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003918 } else if (Tok.getString() == "mips1") {
3919 return parseSetFeature(Mips::FeatureMips1);
3920 } else if (Tok.getString() == "mips2") {
3921 return parseSetFeature(Mips::FeatureMips2);
3922 } else if (Tok.getString() == "mips3") {
3923 return parseSetFeature(Mips::FeatureMips3);
3924 } else if (Tok.getString() == "mips4") {
3925 return parseSetFeature(Mips::FeatureMips4);
3926 } else if (Tok.getString() == "mips5") {
3927 return parseSetFeature(Mips::FeatureMips5);
3928 } else if (Tok.getString() == "mips32") {
3929 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003930 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003931 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003932 } else if (Tok.getString() == "mips32r3") {
3933 return parseSetFeature(Mips::FeatureMips32r3);
3934 } else if (Tok.getString() == "mips32r5") {
3935 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003936 } else if (Tok.getString() == "mips32r6") {
3937 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003938 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003939 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003940 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003941 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003942 } else if (Tok.getString() == "mips64r3") {
3943 return parseSetFeature(Mips::FeatureMips64r3);
3944 } else if (Tok.getString() == "mips64r5") {
3945 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003946 } else if (Tok.getString() == "mips64r6") {
3947 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003948 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003949 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003950 } else if (Tok.getString() == "nodsp") {
3951 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003952 } else if (Tok.getString() == "msa") {
3953 return parseSetMsaDirective();
3954 } else if (Tok.getString() == "nomsa") {
3955 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003956 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003957 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003958 parseSetAssignment();
3959 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003960 }
Jack Carter07c818d2013-01-25 01:31:34 +00003961
Jack Carter0b744b32012-10-04 02:29:46 +00003962 return true;
3963}
3964
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003965/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003966/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003967bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003968 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003969 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3970 for (;;) {
3971 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003972 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003973 return true;
3974
3975 getParser().getStreamer().EmitValue(Value, Size);
3976
3977 if (getLexer().is(AsmToken::EndOfStatement))
3978 break;
3979
Jack Carter07c818d2013-01-25 01:31:34 +00003980 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003981 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003982 Parser.Lex();
3983 }
3984 }
3985
3986 Parser.Lex();
3987 return false;
3988}
3989
Vladimir Medic4c299852013-11-06 11:27:05 +00003990/// parseDirectiveGpWord
3991/// ::= .gpword local_sym
3992bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003993 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003994 const MCExpr *Value;
3995 // EmitGPRel32Value requires an expression, so we are using base class
3996 // method to evaluate the expression.
3997 if (getParser().parseExpression(Value))
3998 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003999 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004000
Vladimir Medice10c1122013-11-13 13:18:04 +00004001 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004002 return Error(getLexer().getLoc(),
4003 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004004 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004005 return false;
4006}
4007
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004008/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004009/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004010bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004011 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004012 const MCExpr *Value;
4013 // EmitGPRel64Value requires an expression, so we are using base class
4014 // method to evaluate the expression.
4015 if (getParser().parseExpression(Value))
4016 return true;
4017 getParser().getStreamer().EmitGPRel64Value(Value);
4018
4019 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004020 return Error(getLexer().getLoc(),
4021 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004022 Parser.Lex(); // Eat EndOfStatement token.
4023 return false;
4024}
4025
Jack Carter0cd3c192014-01-06 23:27:31 +00004026bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004027 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004028 // Get the option token.
4029 AsmToken Tok = Parser.getTok();
4030 // At the moment only identifiers are supported.
4031 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004032 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004033 Parser.eatToEndOfStatement();
4034 return false;
4035 }
4036
4037 StringRef Option = Tok.getIdentifier();
4038
4039 if (Option == "pic0") {
4040 getTargetStreamer().emitDirectiveOptionPic0();
4041 Parser.Lex();
4042 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4043 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004044 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004045 Parser.eatToEndOfStatement();
4046 }
4047 return false;
4048 }
4049
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004050 if (Option == "pic2") {
4051 getTargetStreamer().emitDirectiveOptionPic2();
4052 Parser.Lex();
4053 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4054 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004055 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004056 Parser.eatToEndOfStatement();
4057 }
4058 return false;
4059 }
4060
Jack Carter0cd3c192014-01-06 23:27:31 +00004061 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004062 Warning(Parser.getTok().getLoc(),
4063 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004064 Parser.eatToEndOfStatement();
4065 return false;
4066}
4067
Toma Tabacu9ca50962015-04-16 09:53:47 +00004068/// parseInsnDirective
4069/// ::= .insn
4070bool MipsAsmParser::parseInsnDirective() {
4071 // If this is not the end of the statement, report an error.
4072 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4073 reportParseError("unexpected token, expected end of statement");
4074 return false;
4075 }
4076
4077 // The actual label marking happens in
4078 // MipsELFStreamer::createPendingLabelRelocs().
4079 getTargetStreamer().emitDirectiveInsn();
4080
4081 getParser().Lex(); // Eat EndOfStatement token.
4082 return false;
4083}
4084
Daniel Sanders7e527422014-07-10 13:38:23 +00004085/// parseDirectiveModule
4086/// ::= .module oddspreg
4087/// ::= .module nooddspreg
4088/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004089bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004090 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004091 MCAsmLexer &Lexer = getLexer();
4092 SMLoc L = Lexer.getLoc();
4093
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004094 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004095 // TODO : get a better message.
4096 reportParseError(".module directive must appear before any code");
4097 return false;
4098 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004099
Toma Tabacuc405c822015-01-23 10:40:19 +00004100 StringRef Option;
4101 if (Parser.parseIdentifier(Option)) {
4102 reportParseError("expected .module option identifier");
4103 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004104 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004105
Toma Tabacuc405c822015-01-23 10:40:19 +00004106 if (Option == "oddspreg") {
4107 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4108 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4109
4110 // If this is not the end of the statement, report an error.
4111 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4112 reportParseError("unexpected token, expected end of statement");
4113 return false;
4114 }
4115
4116 return false; // parseDirectiveModule has finished successfully.
4117 } else if (Option == "nooddspreg") {
4118 if (!isABI_O32()) {
4119 Error(L, "'.module nooddspreg' requires the O32 ABI");
4120 return false;
4121 }
4122
4123 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4124 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4125
4126 // If this is not the end of the statement, report an error.
4127 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4128 reportParseError("unexpected token, expected end of statement");
4129 return false;
4130 }
4131
4132 return false; // parseDirectiveModule has finished successfully.
4133 } else if (Option == "fp") {
4134 return parseDirectiveModuleFP();
4135 } else {
4136 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4137 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004138}
4139
4140/// parseDirectiveModuleFP
4141/// ::= =32
4142/// ::= =xx
4143/// ::= =64
4144bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004145 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004146 MCAsmLexer &Lexer = getLexer();
4147
4148 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004149 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004150 return false;
4151 }
4152 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004153
Daniel Sanders7e527422014-07-10 13:38:23 +00004154 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004155 if (!parseFpABIValue(FpABI, ".module"))
4156 return false;
4157
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004158 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004159 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004160 return false;
4161 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004162
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004163 // Emit appropriate flags.
4164 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004165 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004166 return false;
4167}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004168
Daniel Sanders7e527422014-07-10 13:38:23 +00004169bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004170 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004171 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004172 MCAsmLexer &Lexer = getLexer();
4173
4174 if (Lexer.is(AsmToken::Identifier)) {
4175 StringRef Value = Parser.getTok().getString();
4176 Parser.Lex();
4177
4178 if (Value != "xx") {
4179 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4180 return false;
4181 }
4182
4183 if (!isABI_O32()) {
4184 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4185 return false;
4186 }
4187
Daniel Sanders7e527422014-07-10 13:38:23 +00004188 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004189 return true;
4190 }
4191
4192 if (Lexer.is(AsmToken::Integer)) {
4193 unsigned Value = Parser.getTok().getIntVal();
4194 Parser.Lex();
4195
4196 if (Value != 32 && Value != 64) {
4197 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4198 return false;
4199 }
4200
4201 if (Value == 32) {
4202 if (!isABI_O32()) {
4203 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4204 return false;
4205 }
4206
Daniel Sanders7e527422014-07-10 13:38:23 +00004207 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4208 } else
4209 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004210
Daniel Sanders7e527422014-07-10 13:38:23 +00004211 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004212 }
4213
4214 return false;
4215}
4216
Jack Carter0b744b32012-10-04 02:29:46 +00004217bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004218 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004219 StringRef IDVal = DirectiveID.getString();
4220
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004221 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004222 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004223 if (IDVal == ".dword") {
4224 parseDataDirective(8, DirectiveID.getLoc());
4225 return false;
4226 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004227 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004228 StringRef SymbolName;
4229
4230 if (Parser.parseIdentifier(SymbolName)) {
4231 reportParseError("expected identifier after .ent");
4232 return false;
4233 }
4234
4235 // There's an undocumented extension that allows an integer to
4236 // follow the name of the procedure which AFAICS is ignored by GAS.
4237 // Example: .ent foo,2
4238 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4239 if (getLexer().isNot(AsmToken::Comma)) {
4240 // Even though we accept this undocumented extension for compatibility
4241 // reasons, the additional integer argument does not actually change
4242 // the behaviour of the '.ent' directive, so we would like to discourage
4243 // its use. We do this by not referring to the extended version in
4244 // error messages which are not directly related to its use.
4245 reportParseError("unexpected token, expected end of statement");
4246 return false;
4247 }
4248 Parser.Lex(); // Eat the comma.
4249 const MCExpr *DummyNumber;
4250 int64_t DummyNumberVal;
4251 // If the user was explicitly trying to use the extended version,
4252 // we still give helpful extension-related error messages.
4253 if (Parser.parseExpression(DummyNumber)) {
4254 reportParseError("expected number after comma");
4255 return false;
4256 }
4257 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4258 reportParseError("expected an absolute expression after comma");
4259 return false;
4260 }
4261 }
4262
4263 // If this is not the end of the statement, report an error.
4264 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4265 reportParseError("unexpected token, expected end of statement");
4266 return false;
4267 }
4268
4269 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4270
4271 getTargetStreamer().emitDirectiveEnt(*Sym);
4272 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004273 return false;
4274 }
4275
Jack Carter07c818d2013-01-25 01:31:34 +00004276 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004277 StringRef SymbolName;
4278
4279 if (Parser.parseIdentifier(SymbolName)) {
4280 reportParseError("expected identifier after .end");
4281 return false;
4282 }
4283
4284 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4285 reportParseError("unexpected token, expected end of statement");
4286 return false;
4287 }
4288
4289 if (CurrentFn == nullptr) {
4290 reportParseError(".end used without .ent");
4291 return false;
4292 }
4293
4294 if ((SymbolName != CurrentFn->getName())) {
4295 reportParseError(".end symbol does not match .ent symbol");
4296 return false;
4297 }
4298
4299 getTargetStreamer().emitDirectiveEnd(SymbolName);
4300 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004301 return false;
4302 }
4303
Jack Carter07c818d2013-01-25 01:31:34 +00004304 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004305 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4306 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004307 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004308 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4309 reportParseError("expected stack register");
4310 return false;
4311 }
4312
4313 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4314 if (!StackRegOpnd.isGPRAsmReg()) {
4315 reportParseError(StackRegOpnd.getStartLoc(),
4316 "expected general purpose register");
4317 return false;
4318 }
4319 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4320
4321 if (Parser.getTok().is(AsmToken::Comma))
4322 Parser.Lex();
4323 else {
4324 reportParseError("unexpected token, expected comma");
4325 return false;
4326 }
4327
4328 // Parse the frame size.
4329 const MCExpr *FrameSize;
4330 int64_t FrameSizeVal;
4331
4332 if (Parser.parseExpression(FrameSize)) {
4333 reportParseError("expected frame size value");
4334 return false;
4335 }
4336
4337 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4338 reportParseError("frame size not an absolute expression");
4339 return false;
4340 }
4341
4342 if (Parser.getTok().is(AsmToken::Comma))
4343 Parser.Lex();
4344 else {
4345 reportParseError("unexpected token, expected comma");
4346 return false;
4347 }
4348
4349 // Parse the return register.
4350 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004351 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004352 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4353 reportParseError("expected return register");
4354 return false;
4355 }
4356
4357 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4358 if (!ReturnRegOpnd.isGPRAsmReg()) {
4359 reportParseError(ReturnRegOpnd.getStartLoc(),
4360 "expected general purpose register");
4361 return false;
4362 }
4363
4364 // If this is not the end of the statement, report an error.
4365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4366 reportParseError("unexpected token, expected end of statement");
4367 return false;
4368 }
4369
4370 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4371 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004372 return false;
4373 }
4374
Jack Carter07c818d2013-01-25 01:31:34 +00004375 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004376 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004377 }
4378
Daniel Sandersd97a6342014-08-13 10:07:34 +00004379 if (IDVal == ".mask" || IDVal == ".fmask") {
4380 // .mask bitmask, frame_offset
4381 // bitmask: One bit for each register used.
4382 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4383 // first register is expected to be saved.
4384 // Examples:
4385 // .mask 0x80000000, -4
4386 // .fmask 0x80000000, -4
4387 //
Jack Carterbe332172012-09-07 00:48:02 +00004388
Daniel Sandersd97a6342014-08-13 10:07:34 +00004389 // Parse the bitmask
4390 const MCExpr *BitMask;
4391 int64_t BitMaskVal;
4392
4393 if (Parser.parseExpression(BitMask)) {
4394 reportParseError("expected bitmask value");
4395 return false;
4396 }
4397
4398 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4399 reportParseError("bitmask not an absolute expression");
4400 return false;
4401 }
4402
4403 if (Parser.getTok().is(AsmToken::Comma))
4404 Parser.Lex();
4405 else {
4406 reportParseError("unexpected token, expected comma");
4407 return false;
4408 }
4409
4410 // Parse the frame_offset
4411 const MCExpr *FrameOffset;
4412 int64_t FrameOffsetVal;
4413
4414 if (Parser.parseExpression(FrameOffset)) {
4415 reportParseError("expected frame offset value");
4416 return false;
4417 }
4418
4419 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4420 reportParseError("frame offset not an absolute expression");
4421 return false;
4422 }
4423
4424 // If this is not the end of the statement, report an error.
4425 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4426 reportParseError("unexpected token, expected end of statement");
4427 return false;
4428 }
4429
4430 if (IDVal == ".mask")
4431 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4432 else
4433 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004434 return false;
4435 }
4436
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004437 if (IDVal == ".nan")
4438 return parseDirectiveNaN();
4439
Jack Carter07c818d2013-01-25 01:31:34 +00004440 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004441 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004442 return false;
4443 }
4444
Rafael Espindolab59fb732014-03-28 18:50:26 +00004445 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004446 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004447 return false;
4448 }
4449
Jack Carter07c818d2013-01-25 01:31:34 +00004450 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004451 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004452 return false;
4453 }
4454
Jack Carter0cd3c192014-01-06 23:27:31 +00004455 if (IDVal == ".option")
4456 return parseDirectiveOption();
4457
4458 if (IDVal == ".abicalls") {
4459 getTargetStreamer().emitDirectiveAbiCalls();
4460 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004461 Error(Parser.getTok().getLoc(),
4462 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004463 // Clear line
4464 Parser.eatToEndOfStatement();
4465 }
4466 return false;
4467 }
4468
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004469 if (IDVal == ".cpsetup")
4470 return parseDirectiveCPSetup();
4471
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004472 if (IDVal == ".module")
4473 return parseDirectiveModule();
4474
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004475 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4476 return parseInternalDirectiveReallowModule();
4477
Toma Tabacu9ca50962015-04-16 09:53:47 +00004478 if (IDVal == ".insn")
4479 return parseInsnDirective();
4480
Rafael Espindola870c4e92012-01-11 03:56:41 +00004481 return true;
4482}
4483
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004484bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4485 // If this is not the end of the statement, report an error.
4486 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4487 reportParseError("unexpected token, expected end of statement");
4488 return false;
4489 }
4490
4491 getTargetStreamer().reallowModuleDirective();
4492
4493 getParser().Lex(); // Eat EndOfStatement token.
4494 return false;
4495}
4496
Rafael Espindola870c4e92012-01-11 03:56:41 +00004497extern "C" void LLVMInitializeMipsAsmParser() {
4498 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4499 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4500 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4501 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4502}
Jack Carterb4dbc172012-09-05 23:34:03 +00004503
4504#define GET_REGISTER_MATCHER
4505#define GET_MATCHER_IMPLEMENTATION
4506#include "MipsGenAsmMatcher.inc"