blob: cdaf1b723d8d7283dfb45ed135e0838cc846012f [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 Tabacu0d64b202014-08-14 10:29:17 +0000197 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
198 SmallVectorImpl<MCInst> &Instructions);
199
Jack Carter9e65aa32013-03-22 00:05:30 +0000200 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000201 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
202 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000203
204 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
205 SmallVectorImpl<MCInst> &Instructions);
206
Toma Tabacu234482a2015-03-16 12:03:39 +0000207 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
208 SmallVectorImpl<MCInst> &Instructions);
209
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000210 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
211 SmallVectorImpl<MCInst> &Instructions);
212
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000213 bool reportParseError(Twine ErrorMsg);
214 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000215
Jack Carterb5cf5902013-04-17 00:18:04 +0000216 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000217 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000218
Vladimir Medic4c299852013-11-06 11:27:05 +0000219 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000220
221 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000222 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000223 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000224 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000225 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000226 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000227 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000228 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000229 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000230 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000231
232 bool parseSetAtDirective();
233 bool parseSetNoAtDirective();
234 bool parseSetMacroDirective();
235 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000236 bool parseSetMsaDirective();
237 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000238 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000239 bool parseSetReorderDirective();
240 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000241 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000242 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000243 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000244 bool parseSetPopDirective();
245 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000246
Jack Carterd76b2372013-03-21 21:44:16 +0000247 bool parseSetAssignment();
248
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000249 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000250 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000251 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000252 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000253 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000254 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
255 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000256
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000257 bool parseInternalDirectiveReallowModule();
258
Jack Carterdc1e35d2012-09-06 20:00:02 +0000259 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000260
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000261 bool eatComma(StringRef ErrorStr);
262
Jack Carter1ac53222013-02-20 23:11:17 +0000263 int matchCPURegisterName(StringRef Symbol);
264
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000265 int matchHWRegsRegisterName(StringRef Symbol);
266
Jack Carter873c7242013-01-12 01:03:14 +0000267 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000268
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000269 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000270
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000271 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000272
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000273 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000274
Jack Carter5dc8ac92013-09-25 23:50:44 +0000275 int matchMSA128RegisterName(StringRef Name);
276
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000277 int matchMSA128CtrlRegisterName(StringRef Name);
278
Jack Carterd0bd6422013-04-18 00:41:53 +0000279 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000280
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000281 unsigned getGPR(int RegNo);
282
Toma Tabacu89a712b2015-04-15 10:48:56 +0000283 /// Returns the internal register number for the current AT. Also checks if
284 /// the current AT is unavailable (set to $0) and gives an error if it is.
285 /// This should be used in pseudo-instruction expansions which need AT.
286 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000287
288 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000289 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000290
291 // Helper function that checks if the value of a vector index is within the
292 // boundaries of accepted values for each RegisterKind
293 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
294 bool validateMSAIndex(int Val, int RegKind);
295
Daniel Sandersf0df2212014-08-04 12:20:00 +0000296 // Selects a new architecture by updating the FeatureBits with the necessary
297 // info including implied dependencies.
298 // Internally, it clears all the feature bits related to *any* architecture
299 // and selects the new one using the ToggleFeature functionality of the
300 // MCSubtargetInfo object that handles implied dependencies. The reason we
301 // clear all the arch related bits manually is because ToggleFeature only
302 // clears the features that imply the feature being cleared and not the
303 // features implied by the feature being cleared. This is easier to see
304 // with an example:
305 // --------------------------------------------------
306 // | Feature | Implies |
307 // | -------------------------------------------------|
308 // | FeatureMips1 | None |
309 // | FeatureMips2 | FeatureMips1 |
310 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
311 // | FeatureMips4 | FeatureMips3 |
312 // | ... | |
313 // --------------------------------------------------
314 //
315 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
316 // FeatureMipsGP64 | FeatureMips1)
317 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
318 void selectArch(StringRef ArchFeature) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000319 uint64_t FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000320 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
321 STI.setFeatureBits(FeatureBits);
322 setAvailableFeatures(
323 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000324 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000325 }
326
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000327 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000328 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000329 setAvailableFeatures(
330 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000331 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000332 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000333 }
334
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000335 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000336 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000337 setAvailableFeatures(
338 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000339 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000340 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000341 }
342
Rafael Espindola870c4e92012-01-11 03:56:41 +0000343public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000344 enum MipsMatchResultTy {
345 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
346#define GET_OPERAND_DIAGNOSTIC_TYPES
347#include "MipsGenAsmMatcher.inc"
348#undef GET_OPERAND_DIAGNOSTIC_TYPES
349
350 };
351
Joey Gouly0e76fa72013-09-12 10:28:05 +0000352 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000353 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000354 : MCTargetAsmParser(), STI(sti),
355 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
356 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000357 MCAsmParserExtension::Initialize(parser);
358
Toma Tabacu11e14a92015-04-21 11:50:52 +0000359 parser.addAliasForDirective(".asciiz", ".asciz");
360
Jack Carterb4dbc172012-09-05 23:34:03 +0000361 // Initialize the set of available features.
362 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000363
364 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000365 AssemblerOptions.push_back(
366 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000367
368 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000369 AssemblerOptions.push_back(
370 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000371
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000372 getTargetStreamer().updateABIInfo(*this);
373
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000374 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000375 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000376
377 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000378 }
379
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000380 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
381 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
382
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000383 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
384 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
Eric Christophera5762812015-01-26 17:33:46 +0000385 const MipsABIInfo &getABI() const { return ABI; }
386 bool isABI_N32() const { return ABI.IsN32(); }
387 bool isABI_N64() const { return ABI.IsN64(); }
388 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000389 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000390
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000391 bool useOddSPReg() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000392 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
Daniel Sanders7e527422014-07-10 13:38:23 +0000393 }
394
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000395 bool inMicroMipsMode() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000396 return STI.getFeatureBits() & Mips::FeatureMicroMips;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000397 }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000398 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
399 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
400 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
401 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
402 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000403 bool hasMips32() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000404 return (STI.getFeatureBits() & Mips::FeatureMips32);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000405 }
406 bool hasMips64() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000407 return (STI.getFeatureBits() & Mips::FeatureMips64);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000408 }
409 bool hasMips32r2() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000410 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000411 }
412 bool hasMips64r2() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000413 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000414 }
Daniel Sanders17793142015-02-18 16:24:50 +0000415 bool hasMips32r3() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000416 return (STI.getFeatureBits() & Mips::FeatureMips32r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000417 }
418 bool hasMips64r3() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000419 return (STI.getFeatureBits() & Mips::FeatureMips64r3);
Daniel Sanders17793142015-02-18 16:24:50 +0000420 }
421 bool hasMips32r5() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000422 return (STI.getFeatureBits() & Mips::FeatureMips32r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000423 }
424 bool hasMips64r5() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000425 return (STI.getFeatureBits() & Mips::FeatureMips64r5);
Daniel Sanders17793142015-02-18 16:24:50 +0000426 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000427 bool hasMips32r6() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000428 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000429 }
430 bool hasMips64r6() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000431 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432 }
Kai Nackee0245392015-01-27 19:11:28 +0000433 bool hasCnMips() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000434 return (STI.getFeatureBits() & Mips::FeatureCnMips);
Kai Nackee0245392015-01-27 19:11:28 +0000435 }
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000436 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
437 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
438 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000439
440 bool inMips16Mode() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000441 return STI.getFeatureBits() & Mips::FeatureMips16;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000442 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000443
Eric Christophere8ae3e32015-05-07 23:10:21 +0000444 bool useSoftFloat() const {
Michael Kupersteinc3434b32015-05-13 10:28:46 +0000445 return (STI.getFeatureBits() & Mips::FeatureSoftFloat);
Toma Tabacu506cfd02015-05-07 10:29:52 +0000446 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000447
Toma Tabacud9d344b2015-04-27 14:05:04 +0000448 /// Warn if RegIndex is the same as the current AT.
449 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000450};
451}
452
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000453namespace {
454
455/// MipsOperand - Instances of this class represent a parsed Mips machine
456/// instruction.
457class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000458public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000459 /// Broad categories of register classes
460 /// The exact class is finalized by the render method.
461 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000462 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000463 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000465 RegKind_FCC = 4, /// FCC
466 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
467 RegKind_MSACtrl = 16, /// MSA control registers
468 RegKind_COP2 = 32, /// COP2
469 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
470 /// context).
471 RegKind_CCR = 128, /// CCR
472 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000473 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000474
475 /// Potentially any (e.g. $1)
476 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
477 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000478 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000479 };
480
481private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000482 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000483 k_Immediate, /// An immediate (possibly involving symbol references)
484 k_Memory, /// Base + Offset Memory Address
485 k_PhysRegister, /// A physical register from the Mips namespace
486 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000487 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000488 k_RegList, /// A physical register list
489 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000490 } Kind;
491
David Blaikie960ea3f2014-06-08 16:18:35 +0000492public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000493 MipsOperand(KindTy K, MipsAsmParser &Parser)
494 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
495
David Blaikie960ea3f2014-06-08 16:18:35 +0000496private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000497 /// For diagnostics, and checking the assembler temporary
498 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000499
Eric Christopher8996c5d2013-03-15 00:42:55 +0000500 struct Token {
501 const char *Data;
502 unsigned Length;
503 };
504
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 struct PhysRegOp {
506 unsigned Num; /// Register Number
507 };
508
509 struct RegIdxOp {
510 unsigned Index; /// Index into the register class
511 RegKind Kind; /// Bitfield of the kinds it could possibly be
512 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000513 };
514
515 struct ImmOp {
516 const MCExpr *Val;
517 };
518
519 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000520 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000521 const MCExpr *Off;
522 };
523
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000524 struct RegListOp {
525 SmallVector<unsigned, 10> *List;
526 };
527
Jack Carterb4dbc172012-09-05 23:34:03 +0000528 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000529 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000530 struct PhysRegOp PhysReg;
531 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000532 struct ImmOp Imm;
533 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000534 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000535 };
536
537 SMLoc StartLoc, EndLoc;
538
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000539 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000540 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
541 const MCRegisterInfo *RegInfo,
542 SMLoc S, SMLoc E,
543 MipsAsmParser &Parser) {
544 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000545 Op->RegIdx.Index = Index;
546 Op->RegIdx.RegInfo = RegInfo;
547 Op->RegIdx.Kind = RegKind;
548 Op->StartLoc = S;
549 Op->EndLoc = E;
550 return Op;
551 }
552
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000553public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000554 /// Coerce the register to GPR32 and return the real register for the current
555 /// target.
556 unsigned getGPR32Reg() const {
557 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000558 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000559 unsigned ClassID = Mips::GPR32RegClassID;
560 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000561 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000562
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000563 /// Coerce the register to GPR32 and return the real register for the current
564 /// target.
565 unsigned getGPRMM16Reg() const {
566 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
567 unsigned ClassID = Mips::GPR32RegClassID;
568 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
569 }
570
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000571 /// Coerce the register to GPR64 and return the real register for the current
572 /// target.
573 unsigned getGPR64Reg() const {
574 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
575 unsigned ClassID = Mips::GPR64RegClassID;
576 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000577 }
578
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000579private:
580 /// Coerce the register to AFGR64 and return the real register for the current
581 /// target.
582 unsigned getAFGR64Reg() const {
583 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
584 if (RegIdx.Index % 2 != 0)
585 AsmParser.Warning(StartLoc, "Float register should be even.");
586 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
587 .getRegister(RegIdx.Index / 2);
588 }
589
590 /// Coerce the register to FGR64 and return the real register for the current
591 /// target.
592 unsigned getFGR64Reg() const {
593 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
594 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
595 .getRegister(RegIdx.Index);
596 }
597
598 /// Coerce the register to FGR32 and return the real register for the current
599 /// target.
600 unsigned getFGR32Reg() const {
601 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
602 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
603 .getRegister(RegIdx.Index);
604 }
605
606 /// Coerce the register to FGRH32 and return the real register for the current
607 /// target.
608 unsigned getFGRH32Reg() const {
609 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
610 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
611 .getRegister(RegIdx.Index);
612 }
613
614 /// Coerce the register to FCC and return the real register for the current
615 /// target.
616 unsigned getFCCReg() const {
617 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
618 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
619 .getRegister(RegIdx.Index);
620 }
621
622 /// Coerce the register to MSA128 and return the real register for the current
623 /// target.
624 unsigned getMSA128Reg() const {
625 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
626 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
627 // identical
628 unsigned ClassID = Mips::MSA128BRegClassID;
629 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
630 }
631
632 /// Coerce the register to MSACtrl and return the real register for the
633 /// current target.
634 unsigned getMSACtrlReg() const {
635 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
636 unsigned ClassID = Mips::MSACtrlRegClassID;
637 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
638 }
639
640 /// Coerce the register to COP2 and return the real register for the
641 /// current target.
642 unsigned getCOP2Reg() const {
643 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
644 unsigned ClassID = Mips::COP2RegClassID;
645 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
646 }
647
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000648 /// Coerce the register to COP3 and return the real register for the
649 /// current target.
650 unsigned getCOP3Reg() const {
651 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
652 unsigned ClassID = Mips::COP3RegClassID;
653 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
654 }
655
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 /// Coerce the register to ACC64DSP and return the real register for the
657 /// current target.
658 unsigned getACC64DSPReg() const {
659 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
660 unsigned ClassID = Mips::ACC64DSPRegClassID;
661 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
662 }
663
664 /// Coerce the register to HI32DSP and return the real register for the
665 /// current target.
666 unsigned getHI32DSPReg() const {
667 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
668 unsigned ClassID = Mips::HI32DSPRegClassID;
669 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
670 }
671
672 /// Coerce the register to LO32DSP and return the real register for the
673 /// current target.
674 unsigned getLO32DSPReg() const {
675 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
676 unsigned ClassID = Mips::LO32DSPRegClassID;
677 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
678 }
679
680 /// Coerce the register to CCR and return the real register for the
681 /// current target.
682 unsigned getCCRReg() const {
683 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
684 unsigned ClassID = Mips::CCRRegClassID;
685 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
686 }
687
688 /// Coerce the register to HWRegs and return the real register for the
689 /// current target.
690 unsigned getHWRegsReg() const {
691 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
692 unsigned ClassID = Mips::HWRegsRegClassID;
693 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
694 }
695
696public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000697 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000698 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000699 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000700 Inst.addOperand(MCOperand::CreateImm(0));
701 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
702 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
703 else
704 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000705 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000706
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 void addRegOperands(MCInst &Inst, unsigned N) const {
708 llvm_unreachable("Use a custom parser instead");
709 }
710
Daniel Sanders21bce302014-04-01 12:35:23 +0000711 /// Render the operand to an MCInst as a GPR32
712 /// Asserts if the wrong number of operands are requested, or the operand
713 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000714 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
715 assert(N == 1 && "Invalid number of operands!");
716 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
717 }
718
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000719 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
720 assert(N == 1 && "Invalid number of operands!");
721 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
722 }
723
Jozef Kolek1904fa22014-11-24 14:25:53 +0000724 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
725 assert(N == 1 && "Invalid number of operands!");
726 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
727 }
728
Zoran Jovanovic41688672015-02-10 16:36:20 +0000729 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
730 assert(N == 1 && "Invalid number of operands!");
731 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
732 }
733
Daniel Sanders21bce302014-04-01 12:35:23 +0000734 /// Render the operand to an MCInst as a GPR64
735 /// Asserts if the wrong number of operands are requested, or the operand
736 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000737 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
738 assert(N == 1 && "Invalid number of operands!");
739 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
740 }
741
742 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
743 assert(N == 1 && "Invalid number of operands!");
744 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
745 }
746
747 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
748 assert(N == 1 && "Invalid number of operands!");
749 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
750 }
751
752 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
753 assert(N == 1 && "Invalid number of operands!");
754 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000755 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000756 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000757 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
758 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 }
760
761 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
762 assert(N == 1 && "Invalid number of operands!");
763 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
764 }
765
766 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
767 assert(N == 1 && "Invalid number of operands!");
768 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
769 }
770
771 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
772 assert(N == 1 && "Invalid number of operands!");
773 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
774 }
775
776 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
777 assert(N == 1 && "Invalid number of operands!");
778 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
779 }
780
781 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
782 assert(N == 1 && "Invalid number of operands!");
783 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
784 }
785
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000786 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
787 assert(N == 1 && "Invalid number of operands!");
788 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
789 }
790
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
792 assert(N == 1 && "Invalid number of operands!");
793 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
794 }
795
796 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
797 assert(N == 1 && "Invalid number of operands!");
798 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
799 }
800
801 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
802 assert(N == 1 && "Invalid number of operands!");
803 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
804 }
805
806 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
807 assert(N == 1 && "Invalid number of operands!");
808 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
809 }
810
811 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
812 assert(N == 1 && "Invalid number of operands!");
813 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
814 }
815
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000816 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000817 assert(N == 1 && "Invalid number of operands!");
818 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000819 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000820 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000821
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000822 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000823 assert(N == 2 && "Invalid number of operands!");
824
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000826
827 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000828 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000829 }
830
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000831 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
832 assert(N == 2 && "Invalid number of operands!");
833
834 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
835
836 const MCExpr *Expr = getMemOff();
837 addExpr(Inst, Expr);
838 }
839
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000840 void addRegListOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 1 && "Invalid number of operands!");
842
843 for (auto RegNo : getRegList())
844 Inst.addOperand(MCOperand::CreateReg(RegNo));
845 }
846
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000847 void addRegPairOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 2 && "Invalid number of operands!");
849 unsigned RegNo = getRegPair();
850 Inst.addOperand(MCOperand::CreateReg(RegNo++));
851 Inst.addOperand(MCOperand::CreateReg(RegNo));
852 }
853
Zoran Jovanovic41688672015-02-10 16:36:20 +0000854 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
855 assert(N == 2 && "Invalid number of operands!");
856 for (auto RegNo : getRegList())
857 Inst.addOperand(MCOperand::CreateReg(RegNo));
858 }
859
Craig Topper56c590a2014-04-29 07:58:02 +0000860 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 // As a special case until we sort out the definition of div/divu, pretend
862 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
863 if (isGPRAsmReg() && RegIdx.Index == 0)
864 return true;
865
866 return Kind == k_PhysRegister;
867 }
868 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000869 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 bool isConstantImm() const {
871 return isImm() && dyn_cast<MCConstantExpr>(getImm());
872 }
Craig Topper56c590a2014-04-29 07:58:02 +0000873 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874 // Note: It's not possible to pretend that other operand kinds are tokens.
875 // The matcher emitter checks tokens first.
876 return Kind == k_Token;
877 }
Craig Topper56c590a2014-04-29 07:58:02 +0000878 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000879 bool isConstantMemOff() const {
880 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
881 }
882 template <unsigned Bits> bool isMemWithSimmOffset() const {
883 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
884 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000885 bool isMemWithGRPMM16Base() const {
886 return isMem() && getMemBase()->isMM16AsmReg();
887 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000888 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
889 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
890 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
891 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000892 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
893 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
894 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
895 && (getMemBase()->getGPR32Reg() == Mips::SP);
896 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000897 bool isRegList16() const {
898 if (!isRegList())
899 return false;
900
901 int Size = RegList.List->size();
902 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
903 RegList.List->back() != Mips::RA)
904 return false;
905
906 int PrevReg = *RegList.List->begin();
907 for (int i = 1; i < Size - 1; i++) {
908 int Reg = (*(RegList.List))[i];
909 if ( Reg != PrevReg + 1)
910 return false;
911 PrevReg = Reg;
912 }
913
914 return true;
915 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000916 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 bool isLSAImm() const {
918 if (!isConstantImm())
919 return false;
920 int64_t Val = getConstantImm();
921 return 1 <= Val && Val <= 4;
922 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000923 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000924 bool isMovePRegPair() const {
925 if (Kind != k_RegList || RegList.List->size() != 2)
926 return false;
927
928 unsigned R0 = RegList.List->front();
929 unsigned R1 = RegList.List->back();
930
931 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
932 (R0 == Mips::A1 && R1 == Mips::A3) ||
933 (R0 == Mips::A2 && R1 == Mips::A3) ||
934 (R0 == Mips::A0 && R1 == Mips::S5) ||
935 (R0 == Mips::A0 && R1 == Mips::S6) ||
936 (R0 == Mips::A0 && R1 == Mips::A1) ||
937 (R0 == Mips::A0 && R1 == Mips::A2) ||
938 (R0 == Mips::A0 && R1 == Mips::A3))
939 return true;
940
941 return false;
942 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000943
944 StringRef getToken() const {
945 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000946 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000947 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000948 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000949
Craig Topper56c590a2014-04-29 07:58:02 +0000950 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 // As a special case until we sort out the definition of div/divu, pretend
952 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
953 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
954 RegIdx.Kind & RegKind_GPR)
955 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000956
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000957 assert(Kind == k_PhysRegister && "Invalid access!");
958 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000959 }
960
Jack Carterb4dbc172012-09-05 23:34:03 +0000961 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000962 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000963 return Imm.Val;
964 }
965
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000966 int64_t getConstantImm() const {
967 const MCExpr *Val = getImm();
968 return static_cast<const MCConstantExpr *>(Val)->getValue();
969 }
970
971 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000972 assert((Kind == k_Memory) && "Invalid access!");
973 return Mem.Base;
974 }
975
976 const MCExpr *getMemOff() const {
977 assert((Kind == k_Memory) && "Invalid access!");
978 return Mem.Off;
979 }
980
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000981 int64_t getConstantMemOff() const {
982 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
983 }
984
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000985 const SmallVectorImpl<unsigned> &getRegList() const {
986 assert((Kind == k_RegList) && "Invalid access!");
987 return *(RegList.List);
988 }
989
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000990 unsigned getRegPair() const {
991 assert((Kind == k_RegPair) && "Invalid access!");
992 return RegIdx.Index;
993 }
994
David Blaikie960ea3f2014-06-08 16:18:35 +0000995 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
996 MipsAsmParser &Parser) {
997 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000998 Op->Tok.Data = Str.data();
999 Op->Tok.Length = Str.size();
1000 Op->StartLoc = S;
1001 Op->EndLoc = S;
1002 return Op;
1003 }
1004
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001005 /// Create a numeric register (e.g. $1). The exact register remains
1006 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001007 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001008 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001009 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001010 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001012 }
1013
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001014 /// Create a register that is definitely a GPR.
1015 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001016 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001017 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001018 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001019 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001020 }
1021
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 /// Create a register that is definitely a FGR.
1023 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001024 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001025 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001026 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1028 }
1029
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001030 /// Create a register that is definitely a HWReg.
1031 /// This is typically only used for named registers such as $hwr_cpunum.
1032 static std::unique_ptr<MipsOperand>
1033 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1034 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1035 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1036 }
1037
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001038 /// Create a register that is definitely an FCC.
1039 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001040 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001041 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001042 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1044 }
1045
1046 /// Create a register that is definitely an ACC.
1047 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001048 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001049 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001050 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001051 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1052 }
1053
1054 /// Create a register that is definitely an MSA128.
1055 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001056 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001057 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001058 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001059 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1060 }
1061
1062 /// Create a register that is definitely an MSACtrl.
1063 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001064 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001065 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001066 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001067 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1068 }
1069
David Blaikie960ea3f2014-06-08 16:18:35 +00001070 static std::unique_ptr<MipsOperand>
1071 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1072 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001073 Op->Imm.Val = Val;
1074 Op->StartLoc = S;
1075 Op->EndLoc = E;
1076 return Op;
1077 }
1078
David Blaikie960ea3f2014-06-08 16:18:35 +00001079 static std::unique_ptr<MipsOperand>
1080 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1081 SMLoc E, MipsAsmParser &Parser) {
1082 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1083 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001084 Op->Mem.Off = Off;
1085 Op->StartLoc = S;
1086 Op->EndLoc = E;
1087 return Op;
1088 }
1089
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001090 static std::unique_ptr<MipsOperand>
1091 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1092 MipsAsmParser &Parser) {
1093 assert (Regs.size() > 0 && "Empty list not allowed");
1094
1095 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001096 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001097 Op->StartLoc = StartLoc;
1098 Op->EndLoc = EndLoc;
1099 return Op;
1100 }
1101
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001102 static std::unique_ptr<MipsOperand>
1103 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1104 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1105 Op->RegIdx.Index = RegNo;
1106 Op->StartLoc = S;
1107 Op->EndLoc = E;
1108 return Op;
1109 }
1110
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001111 bool isGPRAsmReg() const {
1112 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001113 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001114 bool isMM16AsmReg() const {
1115 if (!(isRegIdx() && RegIdx.Kind))
1116 return false;
1117 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1118 || RegIdx.Index == 16 || RegIdx.Index == 17);
1119 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001120 bool isMM16AsmRegZero() const {
1121 if (!(isRegIdx() && RegIdx.Kind))
1122 return false;
1123 return (RegIdx.Index == 0 ||
1124 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1125 RegIdx.Index == 17);
1126 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001127 bool isMM16AsmRegMoveP() const {
1128 if (!(isRegIdx() && RegIdx.Kind))
1129 return false;
1130 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1131 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1132 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001133 bool isFGRAsmReg() const {
1134 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1135 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001136 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 bool isHWRegsAsmReg() const {
1138 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001139 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 bool isCCRAsmReg() const {
1141 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001142 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001143 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001144 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1145 return false;
1146 if (!AsmParser.hasEightFccRegisters())
1147 return RegIdx.Index == 0;
1148 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001149 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 bool isACCAsmReg() const {
1151 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001152 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 bool isCOP2AsmReg() const {
1154 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001155 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001156 bool isCOP3AsmReg() const {
1157 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1158 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001159 bool isMSA128AsmReg() const {
1160 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001161 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 bool isMSACtrlAsmReg() const {
1163 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001164 }
1165
Jack Carterb4dbc172012-09-05 23:34:03 +00001166 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001167 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001168 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001169 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001170
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001171 virtual ~MipsOperand() {
1172 switch (Kind) {
1173 case k_Immediate:
1174 break;
1175 case k_Memory:
1176 delete Mem.Base;
1177 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001178 case k_RegList:
1179 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001180 case k_PhysRegister:
1181 case k_RegisterIndex:
1182 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001183 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001184 break;
1185 }
1186 }
1187
Craig Topper56c590a2014-04-29 07:58:02 +00001188 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001189 switch (Kind) {
1190 case k_Immediate:
1191 OS << "Imm<";
1192 Imm.Val->print(OS);
1193 OS << ">";
1194 break;
1195 case k_Memory:
1196 OS << "Mem<";
1197 Mem.Base->print(OS);
1198 OS << ", ";
1199 Mem.Off->print(OS);
1200 OS << ">";
1201 break;
1202 case k_PhysRegister:
1203 OS << "PhysReg<" << PhysReg.Num << ">";
1204 break;
1205 case k_RegisterIndex:
1206 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1207 break;
1208 case k_Token:
1209 OS << Tok.Data;
1210 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001211 case k_RegList:
1212 OS << "RegList< ";
1213 for (auto Reg : (*RegList.List))
1214 OS << Reg << " ";
1215 OS << ">";
1216 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001217 case k_RegPair:
1218 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1219 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001220 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001221 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001222}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001223} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001224
Jack Carter9e65aa32013-03-22 00:05:30 +00001225namespace llvm {
1226extern const MCInstrDesc MipsInsts[];
1227}
1228static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1229 return MipsInsts[Opcode];
1230}
1231
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001232static bool hasShortDelaySlot(unsigned Opcode) {
1233 switch (Opcode) {
1234 case Mips::JALS_MM:
1235 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001236 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001237 case Mips::BGEZALS_MM:
1238 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001239 return true;
1240 default:
1241 return false;
1242 }
1243}
1244
Jack Carter9e65aa32013-03-22 00:05:30 +00001245bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001246 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001247 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001248
Jack Carter9e65aa32013-03-22 00:05:30 +00001249 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001250
1251 if (MCID.isBranch() || MCID.isCall()) {
1252 const unsigned Opcode = Inst.getOpcode();
1253 MCOperand Offset;
1254
1255 switch (Opcode) {
1256 default:
1257 break;
Kai Nackee0245392015-01-27 19:11:28 +00001258 case Mips::BBIT0:
1259 case Mips::BBIT032:
1260 case Mips::BBIT1:
1261 case Mips::BBIT132:
1262 assert(hasCnMips() && "instruction only valid for octeon cpus");
1263 // Fall through
1264
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001265 case Mips::BEQ:
1266 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001267 case Mips::BEQ_MM:
1268 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001269 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001270 Offset = Inst.getOperand(2);
1271 if (!Offset.isImm())
1272 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001273 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001274 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001275 if (OffsetToAlignment(Offset.getImm(),
1276 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001277 return Error(IDLoc, "branch to misaligned address");
1278 break;
1279 case Mips::BGEZ:
1280 case Mips::BGTZ:
1281 case Mips::BLEZ:
1282 case Mips::BLTZ:
1283 case Mips::BGEZAL:
1284 case Mips::BLTZAL:
1285 case Mips::BC1F:
1286 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001287 case Mips::BGEZ_MM:
1288 case Mips::BGTZ_MM:
1289 case Mips::BLEZ_MM:
1290 case Mips::BLTZ_MM:
1291 case Mips::BGEZAL_MM:
1292 case Mips::BLTZAL_MM:
1293 case Mips::BC1F_MM:
1294 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001295 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001296 Offset = Inst.getOperand(1);
1297 if (!Offset.isImm())
1298 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001299 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001300 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001301 if (OffsetToAlignment(Offset.getImm(),
1302 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001303 return Error(IDLoc, "branch to misaligned address");
1304 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001305 case Mips::BEQZ16_MM:
1306 case Mips::BNEZ16_MM:
1307 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1308 Offset = Inst.getOperand(1);
1309 if (!Offset.isImm())
1310 break; // We'll deal with this situation later on when applying fixups.
1311 if (!isIntN(8, Offset.getImm()))
1312 return Error(IDLoc, "branch target out of range");
1313 if (OffsetToAlignment(Offset.getImm(), 2LL))
1314 return Error(IDLoc, "branch to misaligned address");
1315 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001316 }
1317 }
1318
Daniel Sandersa84989a2014-06-16 13:25:35 +00001319 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1320 // We still accept it but it is a normal nop.
1321 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1322 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1323 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1324 "nop instruction");
1325 }
1326
Kai Nackee0245392015-01-27 19:11:28 +00001327 if (hasCnMips()) {
1328 const unsigned Opcode = Inst.getOpcode();
1329 MCOperand Opnd;
1330 int Imm;
1331
1332 switch (Opcode) {
1333 default:
1334 break;
1335
1336 case Mips::BBIT0:
1337 case Mips::BBIT032:
1338 case Mips::BBIT1:
1339 case Mips::BBIT132:
1340 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1341 // The offset is handled above
1342 Opnd = Inst.getOperand(1);
1343 if (!Opnd.isImm())
1344 return Error(IDLoc, "expected immediate operand kind");
1345 Imm = Opnd.getImm();
1346 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1347 Opcode == Mips::BBIT1 ? 63 : 31))
1348 return Error(IDLoc, "immediate operand value out of range");
1349 if (Imm > 31) {
1350 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1351 : Mips::BBIT132);
1352 Inst.getOperand(1).setImm(Imm - 32);
1353 }
1354 break;
1355
1356 case Mips::CINS:
1357 case Mips::CINS32:
1358 case Mips::EXTS:
1359 case Mips::EXTS32:
1360 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1361 // Check length
1362 Opnd = Inst.getOperand(3);
1363 if (!Opnd.isImm())
1364 return Error(IDLoc, "expected immediate operand kind");
1365 Imm = Opnd.getImm();
1366 if (Imm < 0 || Imm > 31)
1367 return Error(IDLoc, "immediate operand value out of range");
1368 // Check position
1369 Opnd = Inst.getOperand(2);
1370 if (!Opnd.isImm())
1371 return Error(IDLoc, "expected immediate operand kind");
1372 Imm = Opnd.getImm();
1373 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1374 Opcode == Mips::EXTS ? 63 : 31))
1375 return Error(IDLoc, "immediate operand value out of range");
1376 if (Imm > 31) {
1377 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1378 Inst.getOperand(2).setImm(Imm - 32);
1379 }
1380 break;
1381
1382 case Mips::SEQi:
1383 case Mips::SNEi:
1384 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1385 Opnd = Inst.getOperand(2);
1386 if (!Opnd.isImm())
1387 return Error(IDLoc, "expected immediate operand kind");
1388 Imm = Opnd.getImm();
1389 if (!isInt<10>(Imm))
1390 return Error(IDLoc, "immediate operand value out of range");
1391 break;
1392 }
1393 }
1394
Jack Carter9e65aa32013-03-22 00:05:30 +00001395 if (MCID.mayLoad() || MCID.mayStore()) {
1396 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 // reference or immediate we may have to expand instructions.
1398 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001399 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001400 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1401 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001402 MCOperand &Op = Inst.getOperand(i);
1403 if (Op.isImm()) {
1404 int MemOffset = Op.getImm();
1405 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001406 // Offset can't exceed 16bit value.
1407 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001408 return false;
1409 }
1410 } else if (Op.isExpr()) {
1411 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001413 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001414 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001415 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001416 // Expand symbol.
1417 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001418 return false;
1419 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001420 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001422 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001423 }
1424 }
1425 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001426 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001427 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001428
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001429 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001430 if (MCID.mayLoad()) {
1431 // Try to create 16-bit GP relative load instruction.
1432 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1433 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1434 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1435 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1436 MCOperand &Op = Inst.getOperand(i);
1437 if (Op.isImm()) {
1438 int MemOffset = Op.getImm();
1439 MCOperand &DstReg = Inst.getOperand(0);
1440 MCOperand &BaseReg = Inst.getOperand(1);
1441 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1442 getContext().getRegisterInfo()->getRegClass(
1443 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1444 BaseReg.getReg() == Mips::GP) {
1445 MCInst TmpInst;
1446 TmpInst.setLoc(IDLoc);
1447 TmpInst.setOpcode(Mips::LWGP_MM);
1448 TmpInst.addOperand(MCOperand::CreateReg(DstReg.getReg()));
1449 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
1450 TmpInst.addOperand(MCOperand::CreateImm(MemOffset));
1451 Instructions.push_back(TmpInst);
1452 return false;
1453 }
1454 }
1455 }
1456 } // for
1457 } // if load
1458
1459 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1460
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001461 MCOperand Opnd;
1462 int Imm;
1463
1464 switch (Inst.getOpcode()) {
1465 default:
1466 break;
1467 case Mips::ADDIUS5_MM:
1468 Opnd = Inst.getOperand(2);
1469 if (!Opnd.isImm())
1470 return Error(IDLoc, "expected immediate operand kind");
1471 Imm = Opnd.getImm();
1472 if (Imm < -8 || Imm > 7)
1473 return Error(IDLoc, "immediate operand value out of range");
1474 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001475 case Mips::ADDIUSP_MM:
1476 Opnd = Inst.getOperand(0);
1477 if (!Opnd.isImm())
1478 return Error(IDLoc, "expected immediate operand kind");
1479 Imm = Opnd.getImm();
1480 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1481 Imm % 4 != 0)
1482 return Error(IDLoc, "immediate operand value out of range");
1483 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001484 case Mips::SLL16_MM:
1485 case Mips::SRL16_MM:
1486 Opnd = Inst.getOperand(2);
1487 if (!Opnd.isImm())
1488 return Error(IDLoc, "expected immediate operand kind");
1489 Imm = Opnd.getImm();
1490 if (Imm < 1 || Imm > 8)
1491 return Error(IDLoc, "immediate operand value out of range");
1492 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001493 case Mips::LI16_MM:
1494 Opnd = Inst.getOperand(1);
1495 if (!Opnd.isImm())
1496 return Error(IDLoc, "expected immediate operand kind");
1497 Imm = Opnd.getImm();
1498 if (Imm < -1 || Imm > 126)
1499 return Error(IDLoc, "immediate operand value out of range");
1500 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001501 case Mips::ADDIUR2_MM:
1502 Opnd = Inst.getOperand(2);
1503 if (!Opnd.isImm())
1504 return Error(IDLoc, "expected immediate operand kind");
1505 Imm = Opnd.getImm();
1506 if (!(Imm == 1 || Imm == -1 ||
1507 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1508 return Error(IDLoc, "immediate operand value out of range");
1509 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001510 case Mips::ADDIUR1SP_MM:
1511 Opnd = Inst.getOperand(1);
1512 if (!Opnd.isImm())
1513 return Error(IDLoc, "expected immediate operand kind");
1514 Imm = Opnd.getImm();
1515 if (OffsetToAlignment(Imm, 4LL))
1516 return Error(IDLoc, "misaligned immediate operand value");
1517 if (Imm < 0 || Imm > 255)
1518 return Error(IDLoc, "immediate operand value out of range");
1519 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001520 case Mips::ANDI16_MM:
1521 Opnd = Inst.getOperand(2);
1522 if (!Opnd.isImm())
1523 return Error(IDLoc, "expected immediate operand kind");
1524 Imm = Opnd.getImm();
1525 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1526 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1527 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1528 return Error(IDLoc, "immediate operand value out of range");
1529 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001530 case Mips::LBU16_MM:
1531 Opnd = Inst.getOperand(2);
1532 if (!Opnd.isImm())
1533 return Error(IDLoc, "expected immediate operand kind");
1534 Imm = Opnd.getImm();
1535 if (Imm < -1 || Imm > 14)
1536 return Error(IDLoc, "immediate operand value out of range");
1537 break;
1538 case Mips::SB16_MM:
1539 Opnd = Inst.getOperand(2);
1540 if (!Opnd.isImm())
1541 return Error(IDLoc, "expected immediate operand kind");
1542 Imm = Opnd.getImm();
1543 if (Imm < 0 || Imm > 15)
1544 return Error(IDLoc, "immediate operand value out of range");
1545 break;
1546 case Mips::LHU16_MM:
1547 case Mips::SH16_MM:
1548 Opnd = Inst.getOperand(2);
1549 if (!Opnd.isImm())
1550 return Error(IDLoc, "expected immediate operand kind");
1551 Imm = Opnd.getImm();
1552 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1553 return Error(IDLoc, "immediate operand value out of range");
1554 break;
1555 case Mips::LW16_MM:
1556 case Mips::SW16_MM:
1557 Opnd = Inst.getOperand(2);
1558 if (!Opnd.isImm())
1559 return Error(IDLoc, "expected immediate operand kind");
1560 Imm = Opnd.getImm();
1561 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1562 return Error(IDLoc, "immediate operand value out of range");
1563 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001564 case Mips::CACHE:
1565 case Mips::PREF:
1566 Opnd = Inst.getOperand(2);
1567 if (!Opnd.isImm())
1568 return Error(IDLoc, "expected immediate operand kind");
1569 Imm = Opnd.getImm();
1570 if (!isUInt<5>(Imm))
1571 return Error(IDLoc, "immediate operand value out of range");
1572 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001573 case Mips::ADDIUPC_MM:
1574 MCOperand Opnd = Inst.getOperand(1);
1575 if (!Opnd.isImm())
1576 return Error(IDLoc, "expected immediate operand kind");
1577 int Imm = Opnd.getImm();
1578 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1579 return Error(IDLoc, "immediate operand value out of range");
1580 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001581 }
1582 }
1583
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001584 if (needsExpansion(Inst)) {
1585 if (expandInstruction(Inst, IDLoc, Instructions))
1586 return true;
1587 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001588 Instructions.push_back(Inst);
1589
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001590 // If this instruction has a delay slot and .set reorder is active,
1591 // emit a NOP after it.
1592 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1593 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1594
Jack Carter9e65aa32013-03-22 00:05:30 +00001595 return false;
1596}
1597
Jack Carter30a59822012-10-04 04:03:53 +00001598bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1599
Jack Carterd0bd6422013-04-18 00:41:53 +00001600 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001601 case Mips::LoadImm32:
1602 case Mips::LoadImm64:
1603 case Mips::LoadAddrImm32:
1604 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001605 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001606 case Mips::LWM_MM:
1607 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001608 case Mips::JalOneReg:
1609 case Mips::JalTwoReg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 return true;
1611 default:
1612 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001613 }
1614}
Jack Carter92995f12012-10-06 00:53:28 +00001615
Matheus Almeida3813d572014-06-19 14:39:14 +00001616bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001617 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001619 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001620 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001621 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001622 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001623 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001624 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001625 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001626 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001627 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001628 case Mips::B_MM_Pseudo:
1629 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001630 case Mips::SWM_MM:
1631 case Mips::LWM_MM:
1632 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001633 case Mips::JalOneReg:
1634 case Mips::JalTwoReg:
1635 return expandJalWithRegs(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001636 }
Jack Carter30a59822012-10-04 04:03:53 +00001637}
Jack Carter92995f12012-10-06 00:53:28 +00001638
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001639namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001640template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001641void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001642 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001643 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001644 if (ShiftAmount >= 32) {
1645 tmpInst.setOpcode(Mips::DSLL32);
1646 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1647 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1648 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount - 32));
1649 tmpInst.setLoc(IDLoc);
1650 Instructions.push_back(tmpInst);
1651 tmpInst.clear();
1652 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001653 tmpInst.setOpcode(Mips::DSLL);
1654 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1655 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacua2861db2015-05-01 10:26:47 +00001656 tmpInst.addOperand(MCOperand::CreateImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001657 tmpInst.setLoc(IDLoc);
1658 Instructions.push_back(tmpInst);
1659 tmpInst.clear();
1660 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001661 // There's no need for an ORi if the immediate is 0.
1662 if (Operand.isImm() && Operand.getImm() == 0)
1663 return;
1664
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001665 tmpInst.setOpcode(Mips::ORi);
1666 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1667 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001668 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001669 tmpInst.setLoc(IDLoc);
1670 Instructions.push_back(tmpInst);
1671}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001672
Toma Tabacua2861db2015-05-01 10:26:47 +00001673template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001674void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001675 SmallVectorImpl<MCInst> &Instructions) {
1676 createLShiftOri<ShiftAmount>(MCOperand::CreateImm(Value), RegNo, IDLoc,
1677 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001678}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001679}
1680
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001681bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1682 SmallVectorImpl<MCInst> &Instructions) {
1683 // Create a JALR instruction which is going to replace the pseudo-JAL.
1684 MCInst JalrInst;
1685 JalrInst.setLoc(IDLoc);
1686 const MCOperand FirstRegOp = Inst.getOperand(0);
1687 const unsigned Opcode = Inst.getOpcode();
1688
1689 if (Opcode == Mips::JalOneReg) {
1690 // jal $rs => jalr $rs
1691 if (inMicroMipsMode()) {
1692 JalrInst.setOpcode(Mips::JALR16_MM);
1693 JalrInst.addOperand(FirstRegOp);
1694 } else {
1695 JalrInst.setOpcode(Mips::JALR);
1696 JalrInst.addOperand(MCOperand::CreateReg(Mips::RA));
1697 JalrInst.addOperand(FirstRegOp);
1698 }
1699 } else if (Opcode == Mips::JalTwoReg) {
1700 // jal $rd, $rs => jalr $rd, $rs
1701 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1702 JalrInst.addOperand(FirstRegOp);
1703 const MCOperand SecondRegOp = Inst.getOperand(1);
1704 JalrInst.addOperand(SecondRegOp);
1705 }
1706 Instructions.push_back(JalrInst);
1707
1708 // If .set reorder is active, emit a NOP after it.
1709 if (AssemblerOptions.back()->isReorder()) {
1710 // This is a 32-bit NOP because these 2 pseudo-instructions
1711 // do not have a short delay slot.
1712 MCInst NopInst;
1713 NopInst.setOpcode(Mips::SLL);
1714 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1715 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1716 NopInst.addOperand(MCOperand::CreateImm(0));
1717 Instructions.push_back(NopInst);
1718 }
1719
1720 return false;
1721}
1722
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001723bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1724 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001725 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001726 if (!Is32BitImm && !isGP64bit()) {
1727 Error(IDLoc, "instruction requires a 64-bit architecture");
1728 return true;
1729 }
1730
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001731 bool UseSrcReg = false;
1732 if (SrcReg != Mips::NoRegister)
1733 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001734
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001735 MCInst tmpInst;
1736
Jack Carter92995f12012-10-06 00:53:28 +00001737 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001738 // FIXME: gas has a special case for values that are 000...1111, which
1739 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001741 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001742 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001743 tmpInst.setOpcode(Mips::ORi);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001744 tmpInst.addOperand(MCOperand::CreateReg(DstReg));
1745 tmpInst.addOperand(MCOperand::CreateReg(
1746 UseSrcReg ? SrcReg : (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO)));
Jack Carter92995f12012-10-06 00:53:28 +00001747 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001748 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001749 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001750 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001751 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001752 tmpInst.setOpcode(Mips::ADDiu);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001753 tmpInst.addOperand(MCOperand::CreateReg(DstReg));
1754 tmpInst.addOperand(MCOperand::CreateReg(UseSrcReg ? SrcReg : Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001755 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001756 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001757 } else if ((ImmValue & 0xffffffff) == ImmValue) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001758 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001759 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001760 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001761 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1762 uint16_t Bits15To0 = ImmValue & 0xffff;
1763
Jack Carter873c7242013-01-12 01:03:14 +00001764 tmpInst.setOpcode(Mips::LUi);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001765 tmpInst.addOperand(MCOperand::CreateReg(DstReg));
Toma Tabacu79588102015-04-29 10:19:56 +00001766 tmpInst.addOperand(MCOperand::CreateImm(Bits31To16));
Jack Carter30a59822012-10-04 04:03:53 +00001767 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001768 createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions);
1769
1770 if (UseSrcReg)
1771 createAddu(DstReg, DstReg, SrcReg, Instructions);
1772
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001773 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001774 if (Is32BitImm) {
1775 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001776 return true;
1777 }
1778
1779 // <------- lo32 ------>
1780 // <------- hi32 ------>
1781 // <- hi16 -> <- lo16 ->
1782 // _________________________________
1783 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001784 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001785 // |__________|__________|__________|
1786 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001787 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001788 // li d,j => lui d,hi16(j)
1789 // ori d,d,hi16(lo32(j))
1790 // dsll d,d,16
1791 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001792 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1793 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1794 uint16_t Bits15To0 = ImmValue & 0xffff;
1795
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001796 tmpInst.setOpcode(Mips::LUi);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001797 tmpInst.addOperand(MCOperand::CreateReg(DstReg));
Toma Tabacu79588102015-04-29 10:19:56 +00001798 tmpInst.addOperand(MCOperand::CreateImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001799 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001800 createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions);
1801 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
1802
1803 if (UseSrcReg)
1804 createAddu(DstReg, DstReg, SrcReg, Instructions);
1805
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001806 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001807 if (Is32BitImm) {
1808 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001809 return true;
1810 }
1811
1812 // <------- hi32 ------> <------- lo32 ------>
1813 // <- hi16 -> <- lo16 ->
1814 // ___________________________________________
1815 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001816 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001817 // |__________|__________|__________|__________|
1818 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001819 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001820 // li d,j => lui d,hi16(j)
1821 // ori d,d,lo16(hi32(j))
1822 // dsll d,d,16
1823 // ori d,d,hi16(lo32(j))
1824 // dsll d,d,16
1825 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001826 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1827 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1828 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1829 uint16_t Bits15To0 = ImmValue & 0xffff;
1830
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001831 tmpInst.setOpcode(Mips::LUi);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001832 tmpInst.addOperand(MCOperand::CreateReg(DstReg));
Toma Tabacu79588102015-04-29 10:19:56 +00001833 tmpInst.addOperand(MCOperand::CreateImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001834 Instructions.push_back(tmpInst);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001835 createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001836
1837 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1838 // two left shifts of 16 bits.
1839 if (Bits31To16 == 0) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001840 createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001841 } else {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001842 createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions);
1843 createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001844 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001845
1846 if (UseSrcReg)
1847 createAddu(DstReg, DstReg, SrcReg, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001848 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001849 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001850}
Jack Carter92995f12012-10-06 00:53:28 +00001851
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001852bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1853 SmallVectorImpl<MCInst> &Instructions) {
1854 const MCOperand &ImmOp = Inst.getOperand(1);
1855 assert(ImmOp.isImm() && "expected immediate operand kind");
1856 const MCOperand &DstRegOp = Inst.getOperand(0);
1857 assert(DstRegOp.isReg() && "expected register operand kind");
1858
1859 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1860 Is32BitImm, IDLoc, Instructions))
1861 return true;
1862
1863 return false;
1864}
1865
Matheus Almeida3813d572014-06-19 14:39:14 +00001866bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001867MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001868 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001869 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001870 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1871 "expected immediate operand kind");
1872 if (!ImmOp.isImm()) {
1873 expandLoadAddressSym(Inst, IDLoc, Instructions);
1874 return false;
1875 }
Jack Carter543fdf82012-10-09 23:29:45 +00001876 const MCOperand &SrcRegOp = Inst.getOperand(1);
1877 assert(SrcRegOp.isReg() && "expected register operand kind");
1878 const MCOperand &DstRegOp = Inst.getOperand(0);
1879 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001880
1881 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1882 Is32BitImm, IDLoc, Instructions))
1883 return true;
1884
Matheus Almeida3813d572014-06-19 14:39:14 +00001885 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001886}
1887
Matheus Almeida3813d572014-06-19 14:39:14 +00001888bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001889MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001890 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001891 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001892 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1893 "expected immediate operand kind");
1894 if (!ImmOp.isImm()) {
1895 expandLoadAddressSym(Inst, IDLoc, Instructions);
1896 return false;
1897 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001898 const MCOperand &DstRegOp = Inst.getOperand(0);
1899 assert(DstRegOp.isReg() && "expected register operand kind");
1900
1901 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1902 Is32BitImm, IDLoc, Instructions))
1903 return true;
1904
Matheus Almeida3813d572014-06-19 14:39:14 +00001905 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001906}
1907
Toma Tabacu0d64b202014-08-14 10:29:17 +00001908void
1909MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1910 SmallVectorImpl<MCInst> &Instructions) {
1911 // FIXME: If we do have a valid at register to use, we should generate a
1912 // slightly shorter sequence here.
1913 MCInst tmpInst;
1914 int ExprOperandNo = 1;
1915 // Sometimes the assembly parser will get the immediate expression as
1916 // a $zero + an immediate.
1917 if (Inst.getNumOperands() == 3) {
1918 assert(Inst.getOperand(1).getReg() ==
1919 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1920 ExprOperandNo = 2;
1921 }
1922 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1923 assert(SymOp.isExpr() && "expected symbol operand kind");
1924 const MCOperand &RegOp = Inst.getOperand(0);
1925 unsigned RegNo = RegOp.getReg();
1926 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1927 const MCSymbolRefExpr *HiExpr =
1928 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1929 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1930 const MCSymbolRefExpr *LoExpr =
1931 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1932 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1933 if (isGP64bit()) {
1934 // If it's a 64-bit architecture, expand to:
1935 // la d,sym => lui d,highest(sym)
1936 // ori d,d,higher(sym)
1937 // dsll d,d,16
1938 // ori d,d,hi16(sym)
1939 // dsll d,d,16
1940 // ori d,d,lo16(sym)
1941 const MCSymbolRefExpr *HighestExpr =
1942 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1943 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1944 const MCSymbolRefExpr *HigherExpr =
1945 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1946 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1947
1948 tmpInst.setOpcode(Mips::LUi);
1949 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1950 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1951 Instructions.push_back(tmpInst);
1952
Toma Tabacua2861db2015-05-01 10:26:47 +00001953 createLShiftOri<0>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1954 Instructions);
1955 createLShiftOri<16>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001956 Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001957 createLShiftOri<16>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00001958 Instructions);
1959 } else {
1960 // Otherwise, expand to:
1961 // la d,sym => lui d,hi16(sym)
1962 // ori d,d,lo16(sym)
1963 tmpInst.setOpcode(Mips::LUi);
1964 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1965 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1966 Instructions.push_back(tmpInst);
1967
Toma Tabacua2861db2015-05-01 10:26:47 +00001968 createLShiftOri<0>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1969 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001970 }
1971}
1972
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00001973bool MipsAsmParser::expandUncondBranchMMPseudo(
1974 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00001975 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
1976 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001977
1978 MCOperand Offset = Inst.getOperand(0);
1979 if (Offset.isExpr()) {
1980 Inst.clear();
1981 Inst.setOpcode(Mips::BEQ_MM);
1982 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1983 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1984 Inst.addOperand(MCOperand::CreateExpr(Offset.getExpr()));
1985 } else {
1986 assert(Offset.isImm() && "expected immediate operand kind");
1987 if (isIntN(11, Offset.getImm())) {
1988 // If offset fits into 11 bits then this instruction becomes microMIPS
1989 // 16-bit unconditional branch instruction.
1990 Inst.setOpcode(Mips::B16_MM);
1991 } else {
1992 if (!isIntN(17, Offset.getImm()))
1993 Error(IDLoc, "branch target out of range");
1994 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
1995 Error(IDLoc, "branch to misaligned address");
1996 Inst.clear();
1997 Inst.setOpcode(Mips::BEQ_MM);
1998 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1999 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2000 Inst.addOperand(MCOperand::CreateImm(Offset.getImm()));
2001 }
2002 }
2003 Instructions.push_back(Inst);
2004
Toma Tabacu234482a2015-03-16 12:03:39 +00002005 // If .set reorder is active, emit a NOP after the branch instruction.
2006 if (AssemblerOptions.back()->isReorder())
2007 createNop(true, IDLoc, Instructions);
2008
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002009 return false;
2010}
2011
Jack Carter9e65aa32013-03-22 00:05:30 +00002012void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002013 SmallVectorImpl<MCInst> &Instructions,
2014 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002015 const MCSymbolRefExpr *SR;
2016 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002017 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002018 const MCExpr *ExprOffset;
2019 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002020 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002021 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2022 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002023 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002024 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2025 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002026 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002027 if (isImmOpnd) {
2028 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2029 ImmOffset = Inst.getOperand(2).getImm();
2030 LoOffset = ImmOffset & 0x0000ffff;
2031 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002032 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002033 if (LoOffset & 0x8000)
2034 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002035 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002036 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002037 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002038 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002039 // These are some of the types of expansions we perform here:
2040 // 1) lw $8, sym => lui $8, %hi(sym)
2041 // lw $8, %lo(sym)($8)
2042 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2043 // add $8, $8, $9
2044 // lw $8, %lo(offset)($9)
2045 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2046 // add $at, $at, $8
2047 // lw $8, %lo(offset)($at)
2048 // 4) sw $8, sym => lui $at, %hi(sym)
2049 // sw $8, %lo(sym)($at)
2050 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2051 // add $at, $at, $8
2052 // sw $8, %lo(offset)($at)
2053 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2054 // ldc1 $f0, %lo(sym)($at)
2055 //
2056 // For load instructions we can use the destination register as a temporary
2057 // if base and dst are different (examples 1 and 2) and if the base register
2058 // is general purpose otherwise we must use $at (example 6) and error if it's
2059 // not available. For stores we must use $at (examples 4 and 5) because we
2060 // must not clobber the source register setting up the offset.
2061 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2062 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2063 unsigned RegClassIDOp0 =
2064 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2065 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2066 (RegClassIDOp0 == Mips::GPR64RegClassID);
2067 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002068 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002069 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002070 // At this point we need AT to perform the expansions and we exit if it is
2071 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002072 TmpRegNum = getATReg(IDLoc);
2073 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002074 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002075 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002076
Jack Carter9e65aa32013-03-22 00:05:30 +00002077 TempInst.setOpcode(Mips::LUi);
2078 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2079 if (isImmOpnd)
2080 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
2081 else {
2082 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002083 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00002084 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2085 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
2086 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002087 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002088 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00002090 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002091 }
2092 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002094 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002095 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002098 if (BaseRegNum != Mips::ZERO) {
2099 TempInst.setOpcode(Mips::ADDu);
2100 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2101 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2102 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
2103 Instructions.push_back(TempInst);
2104 TempInst.clear();
2105 }
Alp Tokercb402912014-01-24 17:20:08 +00002106 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 TempInst.setOpcode(Inst.getOpcode());
2109 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
2110 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
2111 if (isImmOpnd)
2112 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
2113 else {
2114 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002115 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2116 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
2117 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00002118 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00002119 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002120 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00002121 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002122 }
2123 }
2124 Instructions.push_back(TempInst);
2125 TempInst.clear();
2126}
2127
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002128bool
2129MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2130 SmallVectorImpl<MCInst> &Instructions) {
2131 unsigned OpNum = Inst.getNumOperands();
2132 unsigned Opcode = Inst.getOpcode();
2133 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2134
2135 assert (Inst.getOperand(OpNum - 1).isImm() &&
2136 Inst.getOperand(OpNum - 2).isReg() &&
2137 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2138
2139 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2140 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2141 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2142 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2143 // It can be implemented as SWM16 or LWM16 instruction.
2144 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2145
2146 Inst.setOpcode(NewOpcode);
2147 Instructions.push_back(Inst);
2148 return false;
2149}
2150
Toma Tabacu234482a2015-03-16 12:03:39 +00002151void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2152 SmallVectorImpl<MCInst> &Instructions) {
2153 MCInst NopInst;
2154 if (hasShortDelaySlot) {
2155 NopInst.setOpcode(Mips::MOVE16_MM);
2156 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2157 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2158 } else {
2159 NopInst.setOpcode(Mips::SLL);
2160 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2161 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
2162 NopInst.addOperand(MCOperand::CreateImm(0));
2163 }
2164 Instructions.push_back(NopInst);
2165}
2166
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002167void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
2168 unsigned TrgReg,
2169 SmallVectorImpl<MCInst> &Instructions) {
2170 MCInst AdduInst;
2171 AdduInst.setOpcode(Mips::ADDu);
2172 AdduInst.addOperand(MCOperand::CreateReg(DstReg));
2173 AdduInst.addOperand(MCOperand::CreateReg(SrcReg));
2174 AdduInst.addOperand(MCOperand::CreateReg(TrgReg));
2175 Instructions.push_back(AdduInst);
2176}
2177
Matheus Almeida595fcab2014-06-11 15:05:56 +00002178unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2179 // As described by the Mips32r2 spec, the registers Rd and Rs for
2180 // jalr.hb must be different.
2181 unsigned Opcode = Inst.getOpcode();
2182
2183 if (Opcode == Mips::JALR_HB &&
2184 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2185 return Match_RequiresDifferentSrcAndDst;
2186
2187 return Match_Success;
2188}
2189
David Blaikie960ea3f2014-06-08 16:18:35 +00002190bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2191 OperandVector &Operands,
2192 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002193 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002194 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002195
Jack Carterb4dbc172012-09-05 23:34:03 +00002196 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002197 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002198 unsigned MatchResult =
2199 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002200
2201 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002202 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002203 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002204 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002205 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002206 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002207 return false;
2208 }
2209 case Match_MissingFeature:
2210 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2211 return true;
2212 case Match_InvalidOperand: {
2213 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002214 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002215 if (ErrorInfo >= Operands.size())
2216 return Error(IDLoc, "too few operands for instruction");
2217
David Blaikie960ea3f2014-06-08 16:18:35 +00002218 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002219 if (ErrorLoc == SMLoc())
2220 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002221 }
2222
2223 return Error(ErrorLoc, "invalid operand for instruction");
2224 }
2225 case Match_MnemonicFail:
2226 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002227 case Match_RequiresDifferentSrcAndDst:
2228 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002229 }
Craig Topper589ceee2015-01-03 08:16:34 +00002230
2231 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002232}
2233
Toma Tabacud9d344b2015-04-27 14:05:04 +00002234void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2235 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2236 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2237 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002238}
2239
Daniel Sandersef638fe2014-10-03 15:37:37 +00002240void
2241MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2242 SMRange Range, bool ShowColors) {
2243 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002244 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002245 ShowColors);
2246}
2247
Jack Carter1ac53222013-02-20 23:11:17 +00002248int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002249 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002250
Vladimir Medic4c299852013-11-06 11:27:05 +00002251 CC = StringSwitch<unsigned>(Name)
2252 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002253 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002254 .Case("a0", 4)
2255 .Case("a1", 5)
2256 .Case("a2", 6)
2257 .Case("a3", 7)
2258 .Case("v0", 2)
2259 .Case("v1", 3)
2260 .Case("s0", 16)
2261 .Case("s1", 17)
2262 .Case("s2", 18)
2263 .Case("s3", 19)
2264 .Case("s4", 20)
2265 .Case("s5", 21)
2266 .Case("s6", 22)
2267 .Case("s7", 23)
2268 .Case("k0", 26)
2269 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002270 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002271 .Case("sp", 29)
2272 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002273 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002274 .Case("ra", 31)
2275 .Case("t0", 8)
2276 .Case("t1", 9)
2277 .Case("t2", 10)
2278 .Case("t3", 11)
2279 .Case("t4", 12)
2280 .Case("t5", 13)
2281 .Case("t6", 14)
2282 .Case("t7", 15)
2283 .Case("t8", 24)
2284 .Case("t9", 25)
2285 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002286
Toma Tabacufda445c2014-09-15 15:33:01 +00002287 if (!(isABI_N32() || isABI_N64()))
2288 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002289
Daniel Sandersef638fe2014-10-03 15:37:37 +00002290 if (12 <= CC && CC <= 15) {
2291 // Name is one of t4-t7
2292 AsmToken RegTok = getLexer().peekTok();
2293 SMRange RegRange = RegTok.getLocRange();
2294
2295 StringRef FixedName = StringSwitch<StringRef>(Name)
2296 .Case("t4", "t0")
2297 .Case("t5", "t1")
2298 .Case("t6", "t2")
2299 .Case("t7", "t3")
2300 .Default("");
2301 assert(FixedName != "" && "Register name is not one of t4-t7.");
2302
2303 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2304 "Did you mean $" + FixedName + "?", RegRange);
2305 }
2306
Toma Tabacufda445c2014-09-15 15:33:01 +00002307 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2308 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2309 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2310 if (8 <= CC && CC <= 11)
2311 CC += 4;
2312
2313 if (CC == -1)
2314 CC = StringSwitch<unsigned>(Name)
2315 .Case("a4", 8)
2316 .Case("a5", 9)
2317 .Case("a6", 10)
2318 .Case("a7", 11)
2319 .Case("kt0", 26)
2320 .Case("kt1", 27)
2321 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002322
2323 return CC;
2324}
Jack Carterd0bd6422013-04-18 00:41:53 +00002325
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002326int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2327 int CC;
2328
2329 CC = StringSwitch<unsigned>(Name)
2330 .Case("hwr_cpunum", 0)
2331 .Case("hwr_synci_step", 1)
2332 .Case("hwr_cc", 2)
2333 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002334 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002335 .Default(-1);
2336
2337 return CC;
2338}
2339
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002340int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002341
Jack Cartera63b16a2012-09-07 00:23:42 +00002342 if (Name[0] == 'f') {
2343 StringRef NumString = Name.substr(1);
2344 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002345 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002346 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002347 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002348 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002349 return IntVal;
2350 }
2351 return -1;
2352}
Jack Cartera63b16a2012-09-07 00:23:42 +00002353
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002354int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2355
2356 if (Name.startswith("fcc")) {
2357 StringRef NumString = Name.substr(3);
2358 unsigned IntVal;
2359 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002360 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002361 if (IntVal > 7) // There are only 8 fcc registers.
2362 return -1;
2363 return IntVal;
2364 }
2365 return -1;
2366}
2367
2368int MipsAsmParser::matchACRegisterName(StringRef Name) {
2369
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002370 if (Name.startswith("ac")) {
2371 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002372 unsigned IntVal;
2373 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002374 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002375 if (IntVal > 3) // There are only 3 acc registers.
2376 return -1;
2377 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002378 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002379 return -1;
2380}
Jack Carterd0bd6422013-04-18 00:41:53 +00002381
Jack Carter5dc8ac92013-09-25 23:50:44 +00002382int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2383 unsigned IntVal;
2384
2385 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2386 return -1;
2387
2388 if (IntVal > 31)
2389 return -1;
2390
2391 return IntVal;
2392}
2393
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002394int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2395 int CC;
2396
2397 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002398 .Case("msair", 0)
2399 .Case("msacsr", 1)
2400 .Case("msaaccess", 2)
2401 .Case("msasave", 3)
2402 .Case("msamodify", 4)
2403 .Case("msarequest", 5)
2404 .Case("msamap", 6)
2405 .Case("msaunmap", 7)
2406 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002407
2408 return CC;
2409}
2410
Toma Tabacu89a712b2015-04-15 10:48:56 +00002411unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002412 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002413 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002414 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002415 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002416 return 0;
2417 }
2418 unsigned AT = getReg(
2419 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002420 return AT;
2421}
Jack Carter0b744b32012-10-04 02:29:46 +00002422
Jack Carterd0bd6422013-04-18 00:41:53 +00002423unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002424 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002425}
2426
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002427unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002428 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002429 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002430}
2431
Jack Carter873c7242013-01-12 01:03:14 +00002432int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002433 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002434 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002435 return -1;
2436
Jack Carter873c7242013-01-12 01:03:14 +00002437 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002438}
2439
Toma Tabacu13964452014-09-04 13:23:44 +00002440bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002441 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002442 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002443
Jack Carter30a59822012-10-04 04:03:53 +00002444 // Check if the current operand has a custom associated parser, if so, try to
2445 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002446 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2447 if (ResTy == MatchOperand_Success)
2448 return false;
2449 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2450 // there was a match, but an error occurred, in which case, just return that
2451 // the operand parsing failed.
2452 if (ResTy == MatchOperand_ParseFail)
2453 return true;
2454
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002455 DEBUG(dbgs() << ".. Generic Parser\n");
2456
Jack Carterb4dbc172012-09-05 23:34:03 +00002457 switch (getLexer().getKind()) {
2458 default:
2459 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2460 return true;
2461 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002462 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002463 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00002464
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002465 // Almost all registers have been parsed by custom parsers. There is only
2466 // one exception to this. $zero (and it's alias $0) will reach this point
2467 // for div, divu, and similar instructions because it is not an operand
2468 // to the instruction definition but an explicit register. Special case
2469 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00002470 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00002471 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002472
Jack Carterd0bd6422013-04-18 00:41:53 +00002473 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00002474 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002475 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00002476 return true;
2477
Jack Carter873c7242013-01-12 01:03:14 +00002478 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00002479 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00002480 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00002481 const MCExpr *Res =
2482 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00002483
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002484 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002485 return false;
2486 }
Vladimir Medic4c299852013-11-06 11:27:05 +00002487 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00002488 case AsmToken::LParen:
2489 case AsmToken::Minus:
2490 case AsmToken::Plus:
2491 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002492 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00002493 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002494 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002495 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002496 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00002497 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00002498 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002499 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002500 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002501 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00002502 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00002503 return true;
2504
Jack Carter873c7242013-01-12 01:03:14 +00002505 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2506
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002507 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00002508 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002509 } // case AsmToken::Percent
2510 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00002511 return true;
2512}
2513
Vladimir Medic4c299852013-11-06 11:27:05 +00002514const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00002515 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00002516 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002518 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00002519 // It's a constant, evaluate reloc value.
2520 int16_t Val;
2521 switch (getVariantKind(RelocStr)) {
2522 case MCSymbolRefExpr::VK_Mips_ABS_LO:
2523 // Get the 1st 16-bits.
2524 Val = MCE->getValue() & 0xffff;
2525 break;
2526 case MCSymbolRefExpr::VK_Mips_ABS_HI:
2527 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
2528 // 16 bits being negative.
2529 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
2530 break;
2531 case MCSymbolRefExpr::VK_Mips_HIGHER:
2532 // Get the 3rd 16-bits.
2533 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
2534 break;
2535 case MCSymbolRefExpr::VK_Mips_HIGHEST:
2536 // Get the 4th 16-bits.
2537 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
2538 break;
2539 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00002540 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00002541 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00002542 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00002543 }
2544
Jack Carterb5cf5902013-04-17 00:18:04 +00002545 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002546 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00002547 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00002548 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00002549 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00002550 return Res;
2551 }
2552
2553 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00002554 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
2555
Sasa Stankovic06c47802014-04-03 10:37:45 +00002556 // Try to create target expression.
2557 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
2558 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002559
Jack Carterd0bd6422013-04-18 00:41:53 +00002560 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
2561 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00002562 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
2563 return Res;
2564 }
2565
2566 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2568 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2569 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002570 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002572 return Expr;
2573}
2574
2575bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2576
2577 switch (Expr->getKind()) {
2578 case MCExpr::Constant:
2579 return true;
2580 case MCExpr::SymbolRef:
2581 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2582 case MCExpr::Binary:
2583 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2584 if (!isEvaluated(BE->getLHS()))
2585 return false;
2586 return isEvaluated(BE->getRHS());
2587 }
2588 case MCExpr::Unary:
2589 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002590 case MCExpr::Target:
2591 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002592 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002593 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002594}
Jack Carterd0bd6422013-04-18 00:41:53 +00002595
Jack Carterb5cf5902013-04-17 00:18:04 +00002596bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002597 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00002598 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002600 if (Tok.isNot(AsmToken::Identifier))
2601 return true;
2602
Yaron Keren075759a2015-03-30 15:42:36 +00002603 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00002604
Jack Carterd0bd6422013-04-18 00:41:53 +00002605 Parser.Lex(); // Eat the identifier.
2606 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002607 const MCExpr *IdVal;
2608 SMLoc EndLoc;
2609
2610 if (getLexer().getKind() == AsmToken::LParen) {
2611 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002612 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002613 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002614 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002615 const AsmToken &nextTok = Parser.getTok();
2616 if (nextTok.isNot(AsmToken::Identifier))
2617 return true;
2618 Str += "(%";
2619 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002620 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002621 if (getLexer().getKind() != AsmToken::LParen)
2622 return true;
2623 } else
2624 break;
2625 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002626 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002627 return true;
2628
2629 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002630 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002631
2632 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002633 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002634
Jack Carterd0bd6422013-04-18 00:41:53 +00002635 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002636 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002637}
2638
Jack Carterb4dbc172012-09-05 23:34:03 +00002639bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2640 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002641 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002642 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002643 if (ResTy == MatchOperand_Success) {
2644 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002645 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002646 StartLoc = Operand.getStartLoc();
2647 EndLoc = Operand.getEndLoc();
2648
2649 // AFAIK, we only support numeric registers and named GPR's in CFI
2650 // directives.
2651 // Don't worry about eating tokens before failing. Using an unrecognised
2652 // register is a parse error.
2653 if (Operand.isGPRAsmReg()) {
2654 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002655 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002656 }
2657
2658 return (RegNo == (unsigned)-1);
2659 }
2660
2661 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002662 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002663}
2664
Jack Carterb5cf5902013-04-17 00:18:04 +00002665bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002666 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00002667 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002668 bool Result = true;
2669
2670 while (getLexer().getKind() == AsmToken::LParen)
2671 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002672
Jack Carterd0bd6422013-04-18 00:41:53 +00002673 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002674 default:
2675 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002676 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002677 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002678 case AsmToken::Integer:
2679 case AsmToken::Minus:
2680 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002681 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002682 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002683 else
2684 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002685 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002686 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002687 break;
Jack Carter873c7242013-01-12 01:03:14 +00002688 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002689 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002690 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002691 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002692}
2693
David Blaikie960ea3f2014-06-08 16:18:35 +00002694MipsAsmParser::OperandMatchResultTy
2695MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002696 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002697 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002698 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002699 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002700 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002701 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002702 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002703 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002704
Jack Carterb5cf5902013-04-17 00:18:04 +00002705 if (getLexer().getKind() == AsmToken::LParen) {
2706 Parser.Lex();
2707 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002708 }
2709
Jack Carterb5cf5902013-04-17 00:18:04 +00002710 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002711 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002712 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002713
Jack Carterd0bd6422013-04-18 00:41:53 +00002714 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002715 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002716 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2717 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002718 SMLoc E =
2719 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002720 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002721 return MatchOperand_Success;
2722 }
2723 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002724 SMLoc E =
2725 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002726
Jack Carterd0bd6422013-04-18 00:41:53 +00002727 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002728 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002729 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002730 S, E, *this);
2731 Operands.push_back(
2732 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002733 return MatchOperand_Success;
2734 }
2735 Error(Parser.getTok().getLoc(), "'(' expected");
2736 return MatchOperand_ParseFail;
2737 }
2738
Jack Carterd0bd6422013-04-18 00:41:53 +00002739 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002740 }
2741
Toma Tabacu13964452014-09-04 13:23:44 +00002742 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002743 if (Res != MatchOperand_Success)
2744 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002745
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002746 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002747 Error(Parser.getTok().getLoc(), "')' expected");
2748 return MatchOperand_ParseFail;
2749 }
2750
Jack Carter873c7242013-01-12 01:03:14 +00002751 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2752
Jack Carterd0bd6422013-04-18 00:41:53 +00002753 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002754
Craig Topper062a2ba2014-04-25 05:30:21 +00002755 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002756 IdVal = MCConstantExpr::Create(0, getContext());
2757
Jack Carterd0bd6422013-04-18 00:41:53 +00002758 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002759 std::unique_ptr<MipsOperand> op(
2760 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002761 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002762 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002763 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002764 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002765 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2766 int64_t Imm;
2767 if (IdVal->EvaluateAsAbsolute(Imm))
2768 IdVal = MCConstantExpr::Create(Imm, getContext());
2769 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2770 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2771 getContext());
2772 }
2773
David Blaikie960ea3f2014-06-08 16:18:35 +00002774 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002775 return MatchOperand_Success;
2776}
2777
David Blaikie960ea3f2014-06-08 16:18:35 +00002778bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002779 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00002780 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2781 if (Sym) {
2782 SMLoc S = Parser.getTok().getLoc();
2783 const MCExpr *Expr;
2784 if (Sym->isVariable())
2785 Expr = Sym->getVariableValue();
2786 else
2787 return false;
2788 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002789 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002790 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002791 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002792 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002793 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002794 if (ResTy == MatchOperand_Success) {
2795 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002796 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002797 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002798 llvm_unreachable("Should never ParseFail");
2799 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002800 }
2801 } else if (Expr->getKind() == MCExpr::Constant) {
2802 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002803 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002804 Operands.push_back(
2805 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002806 return true;
2807 }
2808 }
2809 return false;
2810}
Jack Carterd0bd6422013-04-18 00:41:53 +00002811
Jack Carter873c7242013-01-12 01:03:14 +00002812MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002813MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002814 StringRef Identifier,
2815 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002816 int Index = matchCPURegisterName(Identifier);
2817 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002818 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002819 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2820 return MatchOperand_Success;
2821 }
2822
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002823 Index = matchHWRegsRegisterName(Identifier);
2824 if (Index != -1) {
2825 Operands.push_back(MipsOperand::createHWRegsReg(
2826 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2827 return MatchOperand_Success;
2828 }
2829
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002830 Index = matchFPURegisterName(Identifier);
2831 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002832 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002833 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2834 return MatchOperand_Success;
2835 }
2836
2837 Index = matchFCCRegisterName(Identifier);
2838 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002839 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002840 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2841 return MatchOperand_Success;
2842 }
2843
2844 Index = matchACRegisterName(Identifier);
2845 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002846 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002847 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2848 return MatchOperand_Success;
2849 }
2850
2851 Index = matchMSA128RegisterName(Identifier);
2852 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002853 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002854 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2855 return MatchOperand_Success;
2856 }
2857
2858 Index = matchMSA128CtrlRegisterName(Identifier);
2859 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002860 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002861 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2862 return MatchOperand_Success;
2863 }
2864
2865 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002866}
2867
2868MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002869MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002870 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00002871 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002872
2873 if (Token.is(AsmToken::Identifier)) {
2874 DEBUG(dbgs() << ".. identifier\n");
2875 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002876 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002877 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002878 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002879 } else if (Token.is(AsmToken::Integer)) {
2880 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002881 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002882 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2883 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002884 return MatchOperand_Success;
2885 }
2886
2887 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2888
2889 return MatchOperand_NoMatch;
2890}
2891
David Blaikie960ea3f2014-06-08 16:18:35 +00002892MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002893MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002894 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002895 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002896
2897 auto Token = Parser.getTok();
2898
2899 SMLoc S = Token.getLoc();
2900
2901 if (Token.isNot(AsmToken::Dollar)) {
2902 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2903 if (Token.is(AsmToken::Identifier)) {
2904 if (searchSymbolAlias(Operands))
2905 return MatchOperand_Success;
2906 }
2907 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2908 return MatchOperand_NoMatch;
2909 }
2910 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002911
Toma Tabacu13964452014-09-04 13:23:44 +00002912 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002913 if (ResTy == MatchOperand_Success) {
2914 Parser.Lex(); // $
2915 Parser.Lex(); // identifier
2916 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002917 return ResTy;
2918}
2919
2920MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002921MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002922 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002923 switch (getLexer().getKind()) {
2924 default:
2925 return MatchOperand_NoMatch;
2926 case AsmToken::LParen:
2927 case AsmToken::Minus:
2928 case AsmToken::Plus:
2929 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002930 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002931 case AsmToken::String:
2932 break;
2933 }
2934
2935 const MCExpr *IdVal;
2936 SMLoc S = Parser.getTok().getLoc();
2937 if (getParser().parseExpression(IdVal))
2938 return MatchOperand_ParseFail;
2939
2940 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2941 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2942 return MatchOperand_Success;
2943}
2944
David Blaikie960ea3f2014-06-08 16:18:35 +00002945MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002946MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002947 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002948 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002949
2950 SMLoc S = getLexer().getLoc();
2951
2952 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002953 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002954 if (ResTy != MatchOperand_NoMatch)
2955 return ResTy;
2956
Daniel Sanders315386c2014-04-01 10:40:14 +00002957 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002958 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002959 if (ResTy != MatchOperand_NoMatch)
2960 return ResTy;
2961
Daniel Sandersffd84362014-04-01 10:41:48 +00002962 const MCExpr *Expr = nullptr;
2963 if (Parser.parseExpression(Expr)) {
2964 // We have no way of knowing if a symbol was consumed so we must ParseFail
2965 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002966 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002967 Operands.push_back(
2968 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002969 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002970}
2971
Vladimir Medic2b953d02013-10-01 09:48:56 +00002972MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002973MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002974 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00002975 const MCExpr *IdVal;
2976 // If the first token is '$' we may have register operand.
2977 if (Parser.getTok().is(AsmToken::Dollar))
2978 return MatchOperand_NoMatch;
2979 SMLoc S = Parser.getTok().getLoc();
2980 if (getParser().parseExpression(IdVal))
2981 return MatchOperand_ParseFail;
2982 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002983 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002984 int64_t Val = MCE->getValue();
2985 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2986 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002987 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002988 return MatchOperand_Success;
2989}
2990
Matheus Almeida779c5932013-11-18 12:32:49 +00002991MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002992MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002993 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00002994 switch (getLexer().getKind()) {
2995 default:
2996 return MatchOperand_NoMatch;
2997 case AsmToken::LParen:
2998 case AsmToken::Plus:
2999 case AsmToken::Minus:
3000 case AsmToken::Integer:
3001 break;
3002 }
3003
3004 const MCExpr *Expr;
3005 SMLoc S = Parser.getTok().getLoc();
3006
3007 if (getParser().parseExpression(Expr))
3008 return MatchOperand_ParseFail;
3009
3010 int64_t Val;
3011 if (!Expr->EvaluateAsAbsolute(Val)) {
3012 Error(S, "expected immediate value");
3013 return MatchOperand_ParseFail;
3014 }
3015
3016 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3017 // and because the CPU always adds one to the immediate field, the allowed
3018 // range becomes 1..4. We'll only check the range here and will deal
3019 // with the addition/subtraction when actually decoding/encoding
3020 // the instruction.
3021 if (Val < 1 || Val > 4) {
3022 Error(S, "immediate not in range (1..4)");
3023 return MatchOperand_ParseFail;
3024 }
3025
Jack Carter3b2c96e2014-01-22 23:31:38 +00003026 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003027 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003028 return MatchOperand_Success;
3029}
3030
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003031MipsAsmParser::OperandMatchResultTy
3032MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3033 MCAsmParser &Parser = getParser();
3034 SmallVector<unsigned, 10> Regs;
3035 unsigned RegNo;
3036 unsigned PrevReg = Mips::NoRegister;
3037 bool RegRange = false;
3038 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3039
3040 if (Parser.getTok().isNot(AsmToken::Dollar))
3041 return MatchOperand_ParseFail;
3042
3043 SMLoc S = Parser.getTok().getLoc();
3044 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3045 SMLoc E = getLexer().getLoc();
3046 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3047 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3048 if (RegRange) {
3049 // Remove last register operand because registers from register range
3050 // should be inserted first.
3051 if (RegNo == Mips::RA) {
3052 Regs.push_back(RegNo);
3053 } else {
3054 unsigned TmpReg = PrevReg + 1;
3055 while (TmpReg <= RegNo) {
3056 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3057 Error(E, "invalid register operand");
3058 return MatchOperand_ParseFail;
3059 }
3060
3061 PrevReg = TmpReg;
3062 Regs.push_back(TmpReg++);
3063 }
3064 }
3065
3066 RegRange = false;
3067 } else {
3068 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3069 (RegNo != Mips::RA)) {
3070 Error(E, "$16 or $31 expected");
3071 return MatchOperand_ParseFail;
3072 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3073 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3074 Error(E, "invalid register operand");
3075 return MatchOperand_ParseFail;
3076 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3077 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3078 Error(E, "consecutive register numbers expected");
3079 return MatchOperand_ParseFail;
3080 }
3081
3082 Regs.push_back(RegNo);
3083 }
3084
3085 if (Parser.getTok().is(AsmToken::Minus))
3086 RegRange = true;
3087
3088 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3089 !Parser.getTok().isNot(AsmToken::Comma)) {
3090 Error(E, "',' or '-' expected");
3091 return MatchOperand_ParseFail;
3092 }
3093
3094 Lex(); // Consume comma or minus
3095 if (Parser.getTok().isNot(AsmToken::Dollar))
3096 break;
3097
3098 PrevReg = RegNo;
3099 }
3100
3101 SMLoc E = Parser.getTok().getLoc();
3102 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3103 parseMemOperand(Operands);
3104 return MatchOperand_Success;
3105}
3106
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003107MipsAsmParser::OperandMatchResultTy
3108MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3109 MCAsmParser &Parser = getParser();
3110
3111 SMLoc S = Parser.getTok().getLoc();
3112 if (parseAnyRegister(Operands) != MatchOperand_Success)
3113 return MatchOperand_ParseFail;
3114
3115 SMLoc E = Parser.getTok().getLoc();
3116 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3117 unsigned Reg = Op.getGPR32Reg();
3118 Operands.pop_back();
3119 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3120 return MatchOperand_Success;
3121}
3122
Zoran Jovanovic41688672015-02-10 16:36:20 +00003123MipsAsmParser::OperandMatchResultTy
3124MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3125 MCAsmParser &Parser = getParser();
3126 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3127 SmallVector<unsigned, 10> Regs;
3128
3129 if (Parser.getTok().isNot(AsmToken::Dollar))
3130 return MatchOperand_ParseFail;
3131
3132 SMLoc S = Parser.getTok().getLoc();
3133
3134 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3135 return MatchOperand_ParseFail;
3136
3137 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3138 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3139 Regs.push_back(RegNo);
3140
3141 SMLoc E = Parser.getTok().getLoc();
3142 if (Parser.getTok().isNot(AsmToken::Comma)) {
3143 Error(E, "',' expected");
3144 return MatchOperand_ParseFail;
3145 }
3146
3147 // Remove comma.
3148 Parser.Lex();
3149
3150 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3151 return MatchOperand_ParseFail;
3152
3153 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3154 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3155 Regs.push_back(RegNo);
3156
3157 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3158
3159 return MatchOperand_Success;
3160}
3161
Jack Carterdc1e35d2012-09-06 20:00:02 +00003162MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3163
Vladimir Medic4c299852013-11-06 11:27:05 +00003164 MCSymbolRefExpr::VariantKind VK =
3165 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3166 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3167 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3168 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3169 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3170 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3171 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3172 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3173 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3174 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3175 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3176 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3177 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3178 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3179 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3180 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3181 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3182 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003183 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3184 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3185 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3186 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3187 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3188 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003189 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3190 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003191 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003192
Matheus Almeida2852af82014-04-22 10:15:54 +00003193 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003194
Jack Carterdc1e35d2012-09-06 20:00:02 +00003195 return VK;
3196}
Jack Cartera63b16a2012-09-07 00:23:42 +00003197
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003198/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3199/// either this.
3200/// ::= '(', register, ')'
3201/// handle it before we iterate so we don't get tripped up by the lack of
3202/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003203bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003204 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003205 if (getLexer().is(AsmToken::LParen)) {
3206 Operands.push_back(
3207 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3208 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003209 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003210 SMLoc Loc = getLexer().getLoc();
3211 Parser.eatToEndOfStatement();
3212 return Error(Loc, "unexpected token in argument list");
3213 }
3214 if (Parser.getTok().isNot(AsmToken::RParen)) {
3215 SMLoc Loc = getLexer().getLoc();
3216 Parser.eatToEndOfStatement();
3217 return Error(Loc, "unexpected token, expected ')'");
3218 }
3219 Operands.push_back(
3220 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3221 Parser.Lex();
3222 }
3223 return false;
3224}
3225
3226/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3227/// either one of these.
3228/// ::= '[', register, ']'
3229/// ::= '[', integer, ']'
3230/// handle it before we iterate so we don't get tripped up by the lack of
3231/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003232bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003233 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003234 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003235 if (getLexer().is(AsmToken::LBrac)) {
3236 Operands.push_back(
3237 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3238 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003239 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003240 SMLoc Loc = getLexer().getLoc();
3241 Parser.eatToEndOfStatement();
3242 return Error(Loc, "unexpected token in argument list");
3243 }
3244 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3245 SMLoc Loc = getLexer().getLoc();
3246 Parser.eatToEndOfStatement();
3247 return Error(Loc, "unexpected token, expected ']'");
3248 }
3249 Operands.push_back(
3250 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3251 Parser.Lex();
3252 }
3253 return false;
3254}
3255
David Blaikie960ea3f2014-06-08 16:18:35 +00003256bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3257 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003258 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003259 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003260
3261 // We have reached first instruction, module directive are now forbidden.
3262 getTargetStreamer().forbidModuleDirective();
3263
Vladimir Medic74593e62013-07-17 15:00:42 +00003264 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003265 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003266 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003267 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003268 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003269 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003270 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003271
3272 // Read the remaining operands.
3273 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3274 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003275 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003276 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003277 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003278 return Error(Loc, "unexpected token in argument list");
3279 }
Toma Tabacu13964452014-09-04 13:23:44 +00003280 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003281 return true;
3282 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003283
Jack Carterd0bd6422013-04-18 00:41:53 +00003284 while (getLexer().is(AsmToken::Comma)) {
3285 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003286 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003287 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003288 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003289 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003290 return Error(Loc, "unexpected token in argument list");
3291 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003292 // Parse bracket and parenthesis suffixes before we iterate
3293 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003294 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003295 return true;
3296 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003297 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003298 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003299 }
3300 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003301 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3302 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003303 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003304 return Error(Loc, "unexpected token in argument list");
3305 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003306 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003307 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003308}
3309
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003310bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003311 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003312 SMLoc Loc = getLexer().getLoc();
3313 Parser.eatToEndOfStatement();
3314 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003315}
3316
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003317bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003318 return Error(Loc, ErrorMsg);
3319}
3320
Jack Carter0b744b32012-10-04 02:29:46 +00003321bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003322 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003323 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003324
3325 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003326 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003327
3328 Parser.Lex(); // Eat "noat".
3329
Jack Carterd0bd6422013-04-18 00:41:53 +00003330 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003331 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003332 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003333 return false;
3334 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003335
3336 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003337 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003338 return false;
3339}
Jack Carterd0bd6422013-04-18 00:41:53 +00003340
Jack Carter0b744b32012-10-04 02:29:46 +00003341bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003342 // Line can be: ".set at", which sets $at to $1
3343 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003344 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003345 Parser.Lex(); // Eat "at".
3346
Jack Carter0b744b32012-10-04 02:29:46 +00003347 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003348 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003349 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003350
3351 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003352 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003353 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003354 }
3355
3356 if (getLexer().isNot(AsmToken::Equal)) {
3357 reportParseError("unexpected token, expected equals sign");
3358 return false;
3359 }
3360 Parser.Lex(); // Eat "=".
3361
3362 if (getLexer().isNot(AsmToken::Dollar)) {
3363 if (getLexer().is(AsmToken::EndOfStatement)) {
3364 reportParseError("no register specified");
3365 return false;
3366 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003367 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003368 return false;
3369 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003370 }
3371 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003372
Toma Tabacu16a74492015-02-13 10:30:57 +00003373 // Find out what "reg" is.
3374 unsigned AtRegNo;
3375 const AsmToken &Reg = Parser.getTok();
3376 if (Reg.is(AsmToken::Identifier)) {
3377 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3378 } else if (Reg.is(AsmToken::Integer)) {
3379 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003380 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003381 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003382 return false;
3383 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003384
3385 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003386 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003387 reportParseError("invalid register");
3388 return false;
3389 }
3390 Parser.Lex(); // Eat "reg".
3391
3392 // If this is not the end of the statement, report an error.
3393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3394 reportParseError("unexpected token, expected end of statement");
3395 return false;
3396 }
3397
3398 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3399
3400 Parser.Lex(); // Consume the EndOfStatement.
3401 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003402}
3403
3404bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003405 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003406 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003407 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003409 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003410 return false;
3411 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003412 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003413 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003414 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003415 return false;
3416}
3417
3418bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003419 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003420 Parser.Lex();
3421 // If this is not the end of the statement, report an error.
3422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003423 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003424 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003425 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003426 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003427 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003428 Parser.Lex(); // Consume the EndOfStatement.
3429 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003430}
3431
3432bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003433 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003434 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003435 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003436 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003437 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003438 return false;
3439 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003440 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003441 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003442 return false;
3443}
3444
3445bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003446 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003447 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003448 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003449 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003450 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003451 return false;
3452 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003453 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003454 reportParseError("`noreorder' must be set before `nomacro'");
3455 return false;
3456 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003457 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003458 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003459 return false;
3460}
Jack Carterd76b2372013-03-21 21:44:16 +00003461
Daniel Sanders44934432014-08-07 12:03:36 +00003462bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003463 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003464 Parser.Lex();
3465
3466 // If this is not the end of the statement, report an error.
3467 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003468 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003469
3470 setFeatureBits(Mips::FeatureMSA, "msa");
3471 getTargetStreamer().emitDirectiveSetMsa();
3472 return false;
3473}
3474
3475bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003476 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00003477 Parser.Lex();
3478
3479 // If this is not the end of the statement, report an error.
3480 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003481 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00003482
3483 clearFeatureBits(Mips::FeatureMSA, "msa");
3484 getTargetStreamer().emitDirectiveSetNoMsa();
3485 return false;
3486}
3487
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003488bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003489 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003490 Parser.Lex(); // Eat "nodsp".
3491
3492 // If this is not the end of the statement, report an error.
3493 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3494 reportParseError("unexpected token, expected end of statement");
3495 return false;
3496 }
3497
3498 clearFeatureBits(Mips::FeatureDSP, "dsp");
3499 getTargetStreamer().emitDirectiveSetNoDsp();
3500 return false;
3501}
3502
Toma Tabacucc2502d2014-11-04 17:18:07 +00003503bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003504 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003505 Parser.Lex(); // Eat "mips16".
3506
Jack Carter39536722014-01-22 23:08:42 +00003507 // If this is not the end of the statement, report an error.
3508 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003509 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00003510 return false;
3511 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00003512
3513 setFeatureBits(Mips::FeatureMips16, "mips16");
3514 getTargetStreamer().emitDirectiveSetMips16();
3515 Parser.Lex(); // Consume the EndOfStatement.
3516 return false;
3517}
3518
3519bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003520 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00003521 Parser.Lex(); // Eat "nomips16".
3522
3523 // If this is not the end of the statement, report an error.
3524 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3525 reportParseError("unexpected token, expected end of statement");
3526 return false;
3527 }
3528
3529 clearFeatureBits(Mips::FeatureMips16, "mips16");
3530 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00003531 Parser.Lex(); // Consume the EndOfStatement.
3532 return false;
3533}
3534
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003535bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003536 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00003537 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003538 // Line can be: .set fp=32
3539 // .set fp=xx
3540 // .set fp=64
3541 Parser.Lex(); // Eat fp token
3542 AsmToken Tok = Parser.getTok();
3543 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003544 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003545 return false;
3546 }
3547 Parser.Lex(); // Eat '=' token.
3548 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003549
3550 if (!parseFpABIValue(FpAbiVal, ".set"))
3551 return false;
3552
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003553 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003554 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003555 return false;
3556 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003557 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003558 Parser.Lex(); // Consume the EndOfStatement.
3559 return false;
3560}
3561
Toma Tabacu9db22db2014-09-09 10:15:38 +00003562bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003563 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003564 SMLoc Loc = getLexer().getLoc();
3565
3566 Parser.Lex();
3567 if (getLexer().isNot(AsmToken::EndOfStatement))
3568 return reportParseError("unexpected token, expected end of statement");
3569
3570 // Always keep an element on the options "stack" to prevent the user
3571 // from changing the initial options. This is how we remember them.
3572 if (AssemblerOptions.size() == 2)
3573 return reportParseError(Loc, ".set pop with no .set push");
3574
3575 AssemblerOptions.pop_back();
3576 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
3577
3578 getTargetStreamer().emitDirectiveSetPop();
3579 return false;
3580}
3581
3582bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003583 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003584 Parser.Lex();
3585 if (getLexer().isNot(AsmToken::EndOfStatement))
3586 return reportParseError("unexpected token, expected end of statement");
3587
3588 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00003589 AssemblerOptions.push_back(
3590 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00003591
3592 getTargetStreamer().emitDirectiveSetPush();
3593 return false;
3594}
3595
Jack Carterd76b2372013-03-21 21:44:16 +00003596bool MipsAsmParser::parseSetAssignment() {
3597 StringRef Name;
3598 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00003599 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00003600
3601 if (Parser.parseIdentifier(Name))
3602 reportParseError("expected identifier after .set");
3603
3604 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003605 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00003606 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00003607
Jack Carter3b2c96e2014-01-22 23:31:38 +00003608 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00003609 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00003610
Toma Tabacuf25949b2015-04-07 13:59:39 +00003611 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00003612 Sym->setVariableValue(Value);
3613
3614 return false;
3615}
Jack Carterd0bd6422013-04-18 00:41:53 +00003616
Toma Tabacu26647792014-09-09 12:52:14 +00003617bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003618 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00003619 Parser.Lex();
3620 if (getLexer().isNot(AsmToken::EndOfStatement))
3621 return reportParseError("unexpected token, expected end of statement");
3622
3623 // Reset assembler options to their initial values.
3624 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
3625 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
3626
3627 getTargetStreamer().emitDirectiveSetMips0();
3628 return false;
3629}
3630
Toma Tabacu85618b32014-08-19 14:22:52 +00003631bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003632 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00003633 Parser.Lex();
3634 if (getLexer().isNot(AsmToken::Equal))
3635 return reportParseError("unexpected token, expected equals sign");
3636
3637 Parser.Lex();
3638 StringRef Arch;
3639 if (Parser.parseIdentifier(Arch))
3640 return reportParseError("expected arch identifier");
3641
3642 StringRef ArchFeatureName =
3643 StringSwitch<StringRef>(Arch)
3644 .Case("mips1", "mips1")
3645 .Case("mips2", "mips2")
3646 .Case("mips3", "mips3")
3647 .Case("mips4", "mips4")
3648 .Case("mips5", "mips5")
3649 .Case("mips32", "mips32")
3650 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003651 .Case("mips32r3", "mips32r3")
3652 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003653 .Case("mips32r6", "mips32r6")
3654 .Case("mips64", "mips64")
3655 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00003656 .Case("mips64r3", "mips64r3")
3657 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00003658 .Case("mips64r6", "mips64r6")
3659 .Case("cnmips", "cnmips")
3660 .Case("r4000", "mips3") // This is an implementation of Mips3.
3661 .Default("");
3662
3663 if (ArchFeatureName.empty())
3664 return reportParseError("unsupported architecture");
3665
3666 selectArch(ArchFeatureName);
3667 getTargetStreamer().emitDirectiveSetArch(Arch);
3668 return false;
3669}
3670
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003671bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003672 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003673 Parser.Lex();
3674 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003675 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003676
Matheus Almeida2852af82014-04-22 10:15:54 +00003677 switch (Feature) {
3678 default:
3679 llvm_unreachable("Unimplemented feature");
3680 case Mips::FeatureDSP:
3681 setFeatureBits(Mips::FeatureDSP, "dsp");
3682 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003683 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003684 case Mips::FeatureMicroMips:
3685 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003686 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003687 case Mips::FeatureMips1:
3688 selectArch("mips1");
3689 getTargetStreamer().emitDirectiveSetMips1();
3690 break;
3691 case Mips::FeatureMips2:
3692 selectArch("mips2");
3693 getTargetStreamer().emitDirectiveSetMips2();
3694 break;
3695 case Mips::FeatureMips3:
3696 selectArch("mips3");
3697 getTargetStreamer().emitDirectiveSetMips3();
3698 break;
3699 case Mips::FeatureMips4:
3700 selectArch("mips4");
3701 getTargetStreamer().emitDirectiveSetMips4();
3702 break;
3703 case Mips::FeatureMips5:
3704 selectArch("mips5");
3705 getTargetStreamer().emitDirectiveSetMips5();
3706 break;
3707 case Mips::FeatureMips32:
3708 selectArch("mips32");
3709 getTargetStreamer().emitDirectiveSetMips32();
3710 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003711 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003712 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003713 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003714 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003715 case Mips::FeatureMips32r3:
3716 selectArch("mips32r3");
3717 getTargetStreamer().emitDirectiveSetMips32R3();
3718 break;
3719 case Mips::FeatureMips32r5:
3720 selectArch("mips32r5");
3721 getTargetStreamer().emitDirectiveSetMips32R5();
3722 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003723 case Mips::FeatureMips32r6:
3724 selectArch("mips32r6");
3725 getTargetStreamer().emitDirectiveSetMips32R6();
3726 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003727 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003728 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00003729 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003730 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00003731 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00003732 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00003733 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003734 break;
Daniel Sanders17793142015-02-18 16:24:50 +00003735 case Mips::FeatureMips64r3:
3736 selectArch("mips64r3");
3737 getTargetStreamer().emitDirectiveSetMips64R3();
3738 break;
3739 case Mips::FeatureMips64r5:
3740 selectArch("mips64r5");
3741 getTargetStreamer().emitDirectiveSetMips64R5();
3742 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00003743 case Mips::FeatureMips64r6:
3744 selectArch("mips64r6");
3745 getTargetStreamer().emitDirectiveSetMips64R6();
3746 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003747 }
3748 return false;
3749}
3750
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003751bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003752 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003753 if (getLexer().isNot(AsmToken::Comma)) {
3754 SMLoc Loc = getLexer().getLoc();
3755 Parser.eatToEndOfStatement();
3756 return Error(Loc, ErrorStr);
3757 }
3758
Matheus Almeida2852af82014-04-22 10:15:54 +00003759 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003760 return true;
3761}
3762
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003763bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00003764 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00003765 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003766
Toma Tabacudde4c462014-11-06 10:02:45 +00003767 if (inMips16Mode()) {
3768 reportParseError(".cpload is not supported in Mips16 mode");
3769 return false;
3770 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003771
David Blaikie960ea3f2014-06-08 16:18:35 +00003772 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00003773 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003774 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3775 reportParseError("expected register containing function address");
3776 return false;
3777 }
3778
David Blaikie960ea3f2014-06-08 16:18:35 +00003779 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
3780 if (!RegOpnd.isGPRAsmReg()) {
3781 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003782 return false;
3783 }
3784
Toma Tabacudde4c462014-11-06 10:02:45 +00003785 // If this is not the end of the statement, report an error.
3786 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3787 reportParseError("unexpected token, expected end of statement");
3788 return false;
3789 }
3790
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003791 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003792 return false;
3793}
3794
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003795bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003796 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003797 unsigned FuncReg;
3798 unsigned Save;
3799 bool SaveIsReg = true;
3800
Matheus Almeida7e815762014-06-18 13:08:59 +00003801 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003802 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003803 if (ResTy == MatchOperand_NoMatch) {
3804 reportParseError("expected register containing function address");
3805 Parser.eatToEndOfStatement();
3806 return false;
3807 }
3808
3809 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3810 if (!FuncRegOpnd.isGPRAsmReg()) {
3811 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3812 Parser.eatToEndOfStatement();
3813 return false;
3814 }
3815
3816 FuncReg = FuncRegOpnd.getGPR32Reg();
3817 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003818
Toma Tabacu65f10572014-09-16 15:00:52 +00003819 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003820 return true;
3821
Toma Tabacu13964452014-09-04 13:23:44 +00003822 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003823 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003824 const AsmToken &Tok = Parser.getTok();
3825 if (Tok.is(AsmToken::Integer)) {
3826 Save = Tok.getIntVal();
3827 SaveIsReg = false;
3828 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003829 } else {
3830 reportParseError("expected save register or stack offset");
3831 Parser.eatToEndOfStatement();
3832 return false;
3833 }
3834 } else {
3835 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3836 if (!SaveOpnd.isGPRAsmReg()) {
3837 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3838 Parser.eatToEndOfStatement();
3839 return false;
3840 }
3841 Save = SaveOpnd.getGPR32Reg();
3842 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003843
Toma Tabacu65f10572014-09-16 15:00:52 +00003844 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003845 return true;
3846
Toma Tabacu8874eac2015-02-18 13:46:53 +00003847 const MCExpr *Expr;
3848 if (Parser.parseExpression(Expr)) {
3849 reportParseError("expected expression");
3850 return false;
3851 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003852
Toma Tabacu8874eac2015-02-18 13:46:53 +00003853 if (Expr->getKind() != MCExpr::SymbolRef) {
3854 reportParseError("expected symbol");
3855 return false;
3856 }
3857 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
3858
3859 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
3860 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003861 return false;
3862}
3863
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003864bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003865 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003866 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3867 const AsmToken &Tok = Parser.getTok();
3868
3869 if (Tok.getString() == "2008") {
3870 Parser.Lex();
3871 getTargetStreamer().emitDirectiveNaN2008();
3872 return false;
3873 } else if (Tok.getString() == "legacy") {
3874 Parser.Lex();
3875 getTargetStreamer().emitDirectiveNaNLegacy();
3876 return false;
3877 }
3878 }
3879 // If we don't recognize the option passed to the .nan
3880 // directive (e.g. no option or unknown option), emit an error.
3881 reportParseError("invalid option in .nan directive");
3882 return false;
3883}
3884
Jack Carter0b744b32012-10-04 02:29:46 +00003885bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003886 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003887 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003888 const AsmToken &Tok = Parser.getTok();
3889
3890 if (Tok.getString() == "noat") {
3891 return parseSetNoAtDirective();
3892 } else if (Tok.getString() == "at") {
3893 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003894 } else if (Tok.getString() == "arch") {
3895 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003896 } else if (Tok.getString() == "fp") {
3897 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003898 } else if (Tok.getString() == "pop") {
3899 return parseSetPopDirective();
3900 } else if (Tok.getString() == "push") {
3901 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003902 } else if (Tok.getString() == "reorder") {
3903 return parseSetReorderDirective();
3904 } else if (Tok.getString() == "noreorder") {
3905 return parseSetNoReorderDirective();
3906 } else if (Tok.getString() == "macro") {
3907 return parseSetMacroDirective();
3908 } else if (Tok.getString() == "nomacro") {
3909 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003910 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00003911 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003912 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003913 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003914 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003915 getTargetStreamer().emitDirectiveSetNoMicroMips();
3916 Parser.eatToEndOfStatement();
3917 return false;
3918 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003919 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003920 } else if (Tok.getString() == "mips0") {
3921 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003922 } else if (Tok.getString() == "mips1") {
3923 return parseSetFeature(Mips::FeatureMips1);
3924 } else if (Tok.getString() == "mips2") {
3925 return parseSetFeature(Mips::FeatureMips2);
3926 } else if (Tok.getString() == "mips3") {
3927 return parseSetFeature(Mips::FeatureMips3);
3928 } else if (Tok.getString() == "mips4") {
3929 return parseSetFeature(Mips::FeatureMips4);
3930 } else if (Tok.getString() == "mips5") {
3931 return parseSetFeature(Mips::FeatureMips5);
3932 } else if (Tok.getString() == "mips32") {
3933 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003934 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003935 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003936 } else if (Tok.getString() == "mips32r3") {
3937 return parseSetFeature(Mips::FeatureMips32r3);
3938 } else if (Tok.getString() == "mips32r5") {
3939 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003940 } else if (Tok.getString() == "mips32r6") {
3941 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003942 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003943 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003944 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003945 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00003946 } else if (Tok.getString() == "mips64r3") {
3947 return parseSetFeature(Mips::FeatureMips64r3);
3948 } else if (Tok.getString() == "mips64r5") {
3949 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003950 } else if (Tok.getString() == "mips64r6") {
3951 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003952 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003953 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003954 } else if (Tok.getString() == "nodsp") {
3955 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003956 } else if (Tok.getString() == "msa") {
3957 return parseSetMsaDirective();
3958 } else if (Tok.getString() == "nomsa") {
3959 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003960 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003961 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003962 parseSetAssignment();
3963 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003964 }
Jack Carter07c818d2013-01-25 01:31:34 +00003965
Jack Carter0b744b32012-10-04 02:29:46 +00003966 return true;
3967}
3968
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003969/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003970/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003971bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003972 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00003973 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3974 for (;;) {
3975 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003976 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003977 return true;
3978
3979 getParser().getStreamer().EmitValue(Value, Size);
3980
3981 if (getLexer().is(AsmToken::EndOfStatement))
3982 break;
3983
Jack Carter07c818d2013-01-25 01:31:34 +00003984 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003985 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003986 Parser.Lex();
3987 }
3988 }
3989
3990 Parser.Lex();
3991 return false;
3992}
3993
Vladimir Medic4c299852013-11-06 11:27:05 +00003994/// parseDirectiveGpWord
3995/// ::= .gpword local_sym
3996bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003997 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003998 const MCExpr *Value;
3999 // EmitGPRel32Value requires an expression, so we are using base class
4000 // method to evaluate the expression.
4001 if (getParser().parseExpression(Value))
4002 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004003 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004004
Vladimir Medice10c1122013-11-13 13:18:04 +00004005 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004006 return Error(getLexer().getLoc(),
4007 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004008 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004009 return false;
4010}
4011
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004012/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004013/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004014bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004015 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004016 const MCExpr *Value;
4017 // EmitGPRel64Value requires an expression, so we are using base class
4018 // method to evaluate the expression.
4019 if (getParser().parseExpression(Value))
4020 return true;
4021 getParser().getStreamer().EmitGPRel64Value(Value);
4022
4023 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004024 return Error(getLexer().getLoc(),
4025 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004026 Parser.Lex(); // Eat EndOfStatement token.
4027 return false;
4028}
4029
Jack Carter0cd3c192014-01-06 23:27:31 +00004030bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004031 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004032 // Get the option token.
4033 AsmToken Tok = Parser.getTok();
4034 // At the moment only identifiers are supported.
4035 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004036 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004037 Parser.eatToEndOfStatement();
4038 return false;
4039 }
4040
4041 StringRef Option = Tok.getIdentifier();
4042
4043 if (Option == "pic0") {
4044 getTargetStreamer().emitDirectiveOptionPic0();
4045 Parser.Lex();
4046 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4047 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004048 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004049 Parser.eatToEndOfStatement();
4050 }
4051 return false;
4052 }
4053
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004054 if (Option == "pic2") {
4055 getTargetStreamer().emitDirectiveOptionPic2();
4056 Parser.Lex();
4057 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4058 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004059 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004060 Parser.eatToEndOfStatement();
4061 }
4062 return false;
4063 }
4064
Jack Carter0cd3c192014-01-06 23:27:31 +00004065 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004066 Warning(Parser.getTok().getLoc(),
4067 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004068 Parser.eatToEndOfStatement();
4069 return false;
4070}
4071
Toma Tabacu9ca50962015-04-16 09:53:47 +00004072/// parseInsnDirective
4073/// ::= .insn
4074bool MipsAsmParser::parseInsnDirective() {
4075 // If this is not the end of the statement, report an error.
4076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4077 reportParseError("unexpected token, expected end of statement");
4078 return false;
4079 }
4080
4081 // The actual label marking happens in
4082 // MipsELFStreamer::createPendingLabelRelocs().
4083 getTargetStreamer().emitDirectiveInsn();
4084
4085 getParser().Lex(); // Eat EndOfStatement token.
4086 return false;
4087}
4088
Daniel Sanders7e527422014-07-10 13:38:23 +00004089/// parseDirectiveModule
4090/// ::= .module oddspreg
4091/// ::= .module nooddspreg
4092/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004093bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004094 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004095 MCAsmLexer &Lexer = getLexer();
4096 SMLoc L = Lexer.getLoc();
4097
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004098 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004099 // TODO : get a better message.
4100 reportParseError(".module directive must appear before any code");
4101 return false;
4102 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004103
Toma Tabacuc405c822015-01-23 10:40:19 +00004104 StringRef Option;
4105 if (Parser.parseIdentifier(Option)) {
4106 reportParseError("expected .module option identifier");
4107 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004108 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004109
Toma Tabacuc405c822015-01-23 10:40:19 +00004110 if (Option == "oddspreg") {
4111 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
4112 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4113
4114 // If this is not the end of the statement, report an error.
4115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4116 reportParseError("unexpected token, expected end of statement");
4117 return false;
4118 }
4119
4120 return false; // parseDirectiveModule has finished successfully.
4121 } else if (Option == "nooddspreg") {
4122 if (!isABI_O32()) {
4123 Error(L, "'.module nooddspreg' requires the O32 ABI");
4124 return false;
4125 }
4126
4127 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
4128 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4129
4130 // If this is not the end of the statement, report an error.
4131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4132 reportParseError("unexpected token, expected end of statement");
4133 return false;
4134 }
4135
4136 return false; // parseDirectiveModule has finished successfully.
4137 } else if (Option == "fp") {
4138 return parseDirectiveModuleFP();
4139 } else {
4140 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4141 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004142}
4143
4144/// parseDirectiveModuleFP
4145/// ::= =32
4146/// ::= =xx
4147/// ::= =64
4148bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004149 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004150 MCAsmLexer &Lexer = getLexer();
4151
4152 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004153 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004154 return false;
4155 }
4156 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004157
Daniel Sanders7e527422014-07-10 13:38:23 +00004158 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004159 if (!parseFpABIValue(FpABI, ".module"))
4160 return false;
4161
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004162 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004163 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004164 return false;
4165 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004166
Daniel Sanders7201a3e2014-07-08 10:35:52 +00004167 // Emit appropriate flags.
4168 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00004169 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004170 return false;
4171}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004172
Daniel Sanders7e527422014-07-10 13:38:23 +00004173bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004174 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004175 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004176 MCAsmLexer &Lexer = getLexer();
4177
4178 if (Lexer.is(AsmToken::Identifier)) {
4179 StringRef Value = Parser.getTok().getString();
4180 Parser.Lex();
4181
4182 if (Value != "xx") {
4183 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4184 return false;
4185 }
4186
4187 if (!isABI_O32()) {
4188 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4189 return false;
4190 }
4191
Daniel Sanders7e527422014-07-10 13:38:23 +00004192 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004193 return true;
4194 }
4195
4196 if (Lexer.is(AsmToken::Integer)) {
4197 unsigned Value = Parser.getTok().getIntVal();
4198 Parser.Lex();
4199
4200 if (Value != 32 && Value != 64) {
4201 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4202 return false;
4203 }
4204
4205 if (Value == 32) {
4206 if (!isABI_O32()) {
4207 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4208 return false;
4209 }
4210
Daniel Sanders7e527422014-07-10 13:38:23 +00004211 FpABI = MipsABIFlagsSection::FpABIKind::S32;
4212 } else
4213 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004214
Daniel Sanders7e527422014-07-10 13:38:23 +00004215 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004216 }
4217
4218 return false;
4219}
4220
Jack Carter0b744b32012-10-04 02:29:46 +00004221bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004222 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004223 StringRef IDVal = DirectiveID.getString();
4224
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004225 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004226 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004227 if (IDVal == ".dword") {
4228 parseDataDirective(8, DirectiveID.getLoc());
4229 return false;
4230 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004231 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004232 StringRef SymbolName;
4233
4234 if (Parser.parseIdentifier(SymbolName)) {
4235 reportParseError("expected identifier after .ent");
4236 return false;
4237 }
4238
4239 // There's an undocumented extension that allows an integer to
4240 // follow the name of the procedure which AFAICS is ignored by GAS.
4241 // Example: .ent foo,2
4242 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4243 if (getLexer().isNot(AsmToken::Comma)) {
4244 // Even though we accept this undocumented extension for compatibility
4245 // reasons, the additional integer argument does not actually change
4246 // the behaviour of the '.ent' directive, so we would like to discourage
4247 // its use. We do this by not referring to the extended version in
4248 // error messages which are not directly related to its use.
4249 reportParseError("unexpected token, expected end of statement");
4250 return false;
4251 }
4252 Parser.Lex(); // Eat the comma.
4253 const MCExpr *DummyNumber;
4254 int64_t DummyNumberVal;
4255 // If the user was explicitly trying to use the extended version,
4256 // we still give helpful extension-related error messages.
4257 if (Parser.parseExpression(DummyNumber)) {
4258 reportParseError("expected number after comma");
4259 return false;
4260 }
4261 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
4262 reportParseError("expected an absolute expression after comma");
4263 return false;
4264 }
4265 }
4266
4267 // If this is not the end of the statement, report an error.
4268 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4269 reportParseError("unexpected token, expected end of statement");
4270 return false;
4271 }
4272
4273 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
4274
4275 getTargetStreamer().emitDirectiveEnt(*Sym);
4276 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004277 return false;
4278 }
4279
Jack Carter07c818d2013-01-25 01:31:34 +00004280 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004281 StringRef SymbolName;
4282
4283 if (Parser.parseIdentifier(SymbolName)) {
4284 reportParseError("expected identifier after .end");
4285 return false;
4286 }
4287
4288 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4289 reportParseError("unexpected token, expected end of statement");
4290 return false;
4291 }
4292
4293 if (CurrentFn == nullptr) {
4294 reportParseError(".end used without .ent");
4295 return false;
4296 }
4297
4298 if ((SymbolName != CurrentFn->getName())) {
4299 reportParseError(".end symbol does not match .ent symbol");
4300 return false;
4301 }
4302
4303 getTargetStreamer().emitDirectiveEnd(SymbolName);
4304 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004305 return false;
4306 }
4307
Jack Carter07c818d2013-01-25 01:31:34 +00004308 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004309 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4310 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004311 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004312 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4313 reportParseError("expected stack register");
4314 return false;
4315 }
4316
4317 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4318 if (!StackRegOpnd.isGPRAsmReg()) {
4319 reportParseError(StackRegOpnd.getStartLoc(),
4320 "expected general purpose register");
4321 return false;
4322 }
4323 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4324
4325 if (Parser.getTok().is(AsmToken::Comma))
4326 Parser.Lex();
4327 else {
4328 reportParseError("unexpected token, expected comma");
4329 return false;
4330 }
4331
4332 // Parse the frame size.
4333 const MCExpr *FrameSize;
4334 int64_t FrameSizeVal;
4335
4336 if (Parser.parseExpression(FrameSize)) {
4337 reportParseError("expected frame size value");
4338 return false;
4339 }
4340
4341 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
4342 reportParseError("frame size not an absolute expression");
4343 return false;
4344 }
4345
4346 if (Parser.getTok().is(AsmToken::Comma))
4347 Parser.Lex();
4348 else {
4349 reportParseError("unexpected token, expected comma");
4350 return false;
4351 }
4352
4353 // Parse the return register.
4354 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004355 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004356 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4357 reportParseError("expected return register");
4358 return false;
4359 }
4360
4361 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4362 if (!ReturnRegOpnd.isGPRAsmReg()) {
4363 reportParseError(ReturnRegOpnd.getStartLoc(),
4364 "expected general purpose register");
4365 return false;
4366 }
4367
4368 // If this is not the end of the statement, report an error.
4369 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4370 reportParseError("unexpected token, expected end of statement");
4371 return false;
4372 }
4373
4374 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
4375 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00004376 return false;
4377 }
4378
Jack Carter07c818d2013-01-25 01:31:34 +00004379 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00004380 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00004381 }
4382
Daniel Sandersd97a6342014-08-13 10:07:34 +00004383 if (IDVal == ".mask" || IDVal == ".fmask") {
4384 // .mask bitmask, frame_offset
4385 // bitmask: One bit for each register used.
4386 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
4387 // first register is expected to be saved.
4388 // Examples:
4389 // .mask 0x80000000, -4
4390 // .fmask 0x80000000, -4
4391 //
Jack Carterbe332172012-09-07 00:48:02 +00004392
Daniel Sandersd97a6342014-08-13 10:07:34 +00004393 // Parse the bitmask
4394 const MCExpr *BitMask;
4395 int64_t BitMaskVal;
4396
4397 if (Parser.parseExpression(BitMask)) {
4398 reportParseError("expected bitmask value");
4399 return false;
4400 }
4401
4402 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
4403 reportParseError("bitmask not an absolute expression");
4404 return false;
4405 }
4406
4407 if (Parser.getTok().is(AsmToken::Comma))
4408 Parser.Lex();
4409 else {
4410 reportParseError("unexpected token, expected comma");
4411 return false;
4412 }
4413
4414 // Parse the frame_offset
4415 const MCExpr *FrameOffset;
4416 int64_t FrameOffsetVal;
4417
4418 if (Parser.parseExpression(FrameOffset)) {
4419 reportParseError("expected frame offset value");
4420 return false;
4421 }
4422
4423 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
4424 reportParseError("frame offset not an absolute expression");
4425 return false;
4426 }
4427
4428 // If this is not the end of the statement, report an error.
4429 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4430 reportParseError("unexpected token, expected end of statement");
4431 return false;
4432 }
4433
4434 if (IDVal == ".mask")
4435 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
4436 else
4437 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00004438 return false;
4439 }
4440
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004441 if (IDVal == ".nan")
4442 return parseDirectiveNaN();
4443
Jack Carter07c818d2013-01-25 01:31:34 +00004444 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004445 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00004446 return false;
4447 }
4448
Rafael Espindolab59fb732014-03-28 18:50:26 +00004449 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004450 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004451 return false;
4452 }
4453
Jack Carter07c818d2013-01-25 01:31:34 +00004454 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004455 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00004456 return false;
4457 }
4458
Jack Carter0cd3c192014-01-06 23:27:31 +00004459 if (IDVal == ".option")
4460 return parseDirectiveOption();
4461
4462 if (IDVal == ".abicalls") {
4463 getTargetStreamer().emitDirectiveAbiCalls();
4464 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004465 Error(Parser.getTok().getLoc(),
4466 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004467 // Clear line
4468 Parser.eatToEndOfStatement();
4469 }
4470 return false;
4471 }
4472
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004473 if (IDVal == ".cpsetup")
4474 return parseDirectiveCPSetup();
4475
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004476 if (IDVal == ".module")
4477 return parseDirectiveModule();
4478
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004479 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
4480 return parseInternalDirectiveReallowModule();
4481
Toma Tabacu9ca50962015-04-16 09:53:47 +00004482 if (IDVal == ".insn")
4483 return parseInsnDirective();
4484
Rafael Espindola870c4e92012-01-11 03:56:41 +00004485 return true;
4486}
4487
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00004488bool MipsAsmParser::parseInternalDirectiveReallowModule() {
4489 // If this is not the end of the statement, report an error.
4490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4491 reportParseError("unexpected token, expected end of statement");
4492 return false;
4493 }
4494
4495 getTargetStreamer().reallowModuleDirective();
4496
4497 getParser().Lex(); // Eat EndOfStatement token.
4498 return false;
4499}
4500
Rafael Espindola870c4e92012-01-11 03:56:41 +00004501extern "C" void LLVMInitializeMipsAsmParser() {
4502 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
4503 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
4504 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
4505 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
4506}
Jack Carterb4dbc172012-09-05 23:34:03 +00004507
4508#define GET_REGISTER_MATCHER
4509#define GET_MATCHER_IMPLEMENTATION
4510#include "MipsGenAsmMatcher.inc"