blob: 8f7968939cb24979e0fc4198b6a2a3ae69531d7e [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 Tabacu465acfd2015-06-09 13:33:26 +000046 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 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 Tabacu465acfd2015-06-09 13:33:26 +000073 const FeatureBitset &getFeatures() const { return Features; }
74 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000075
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 Kupersteindb0712f2015-05-26 10:47:10 +000081 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000082
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000087 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
Michael Kupersteindb0712f2015-05-26 10:47:10 +000091const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
92 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
93 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
94 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
95 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
96 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
97 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
98 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
99 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
100};
101
Jack Carter0b744b32012-10-04 02:29:46 +0000102namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000103class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000104 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000105 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 return static_cast<MipsTargetStreamer &>(TS);
107 }
108
Jack Carterb4dbc172012-09-05 23:34:03 +0000109 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Jack Carter0b744b32012-10-04 02:29:46 +0000117
Daniel Sandersef638fe2014-10-03 15:37:37 +0000118 // Print a warning along with its fix-it message at the given range.
119 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
120 SMRange Range, bool ShowColors = true);
121
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000122#define GET_ASSEMBLER_HEADER
123#include "MipsGenAsmMatcher.inc"
124
Matheus Almeida595fcab2014-06-11 15:05:56 +0000125 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
126
Chad Rosier49963552012-10-13 00:26:04 +0000127 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000128 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000129 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000130 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000131
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000133 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000134
Toma Tabacu13964452014-09-04 13:23:44 +0000135 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138
David Blaikie960ea3f2014-06-08 16:18:35 +0000139 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
140 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Craig Topper56c590a2014-04-29 07:58:02 +0000142 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000143
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000148 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000149
Jack Carter873c7242013-01-12 01:03:14 +0000150 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000151 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000154
Toma Tabacu13964452014-09-04 13:23:44 +0000155 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000158
David Blaikie960ea3f2014-06-08 16:18:35 +0000159 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000160
Toma Tabacu13964452014-09-04 13:23:44 +0000161 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000162
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000163 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000164 parseRegisterPair (OperandVector &Operands);
165
166 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000167 parseMovePRegPair(OperandVector &Operands);
168
169 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000170 parseRegisterList (OperandVector &Operands);
171
David Blaikie960ea3f2014-06-08 16:18:35 +0000172 bool searchSymbolAlias(OperandVector &Operands);
173
Toma Tabacu13964452014-09-04 13:23:44 +0000174 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000175
Jack Carter30a59822012-10-04 04:03:53 +0000176 bool needsExpansion(MCInst &Inst);
177
Matheus Almeida3813d572014-06-19 14:39:14 +0000178 // Expands assembly pseudo instructions.
179 // Returns false on success, true otherwise.
180 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000181 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000182
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000183 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
185
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
187 bool Is32BitImm, SMLoc IDLoc,
188 SmallVectorImpl<MCInst> &Instructions);
189
Toma Tabacuf712ede2015-06-17 14:31:51 +0000190 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
191 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
192 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000193
Toma Tabacu00e98672015-05-01 12:19:27 +0000194 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000195 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000196
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000197 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000198 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000200 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000201 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000202 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000204
Jack Carter9e65aa32013-03-22 00:05:30 +0000205 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000206 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
207 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000208
209 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
210 SmallVectorImpl<MCInst> &Instructions);
211
Toma Tabacue1e460d2015-06-11 10:36:10 +0000212 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
213 SmallVectorImpl<MCInst> &Instructions);
214
Toma Tabacu1a108322015-06-17 13:20:24 +0000215 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
216 SmallVectorImpl<MCInst> &Instructions);
217
Toma Tabacud88d79c2015-06-23 14:39:42 +0000218 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000221 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacu234482a2015-03-16 12:03:39 +0000224 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000228 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000229
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000230 bool reportParseError(Twine ErrorMsg);
231 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000232
Jack Carterb5cf5902013-04-17 00:18:04 +0000233 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000234 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Vladimir Medic4c299852013-11-06 11:27:05 +0000236 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000237
238 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000239 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000240 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000241 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000242 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000243 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000244 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000245 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000246 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000247 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000248
249 bool parseSetAtDirective();
250 bool parseSetNoAtDirective();
251 bool parseSetMacroDirective();
252 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000253 bool parseSetMsaDirective();
254 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000255 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000256 bool parseSetReorderDirective();
257 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000258 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000259 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000260 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000261 bool parseSetOddSPRegDirective();
262 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000263 bool parseSetPopDirective();
264 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000265 bool parseSetSoftFloatDirective();
266 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000267
Jack Carterd76b2372013-03-21 21:44:16 +0000268 bool parseSetAssignment();
269
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000270 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000271 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000272 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000273 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000274 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000275 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
276 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000277
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000278 bool parseInternalDirectiveReallowModule();
279
Jack Carterdc1e35d2012-09-06 20:00:02 +0000280 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000281
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000282 bool eatComma(StringRef ErrorStr);
283
Jack Carter1ac53222013-02-20 23:11:17 +0000284 int matchCPURegisterName(StringRef Symbol);
285
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000286 int matchHWRegsRegisterName(StringRef Symbol);
287
Jack Carter873c7242013-01-12 01:03:14 +0000288 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000289
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000290 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000291
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000292 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000293
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000294 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000295
Jack Carter5dc8ac92013-09-25 23:50:44 +0000296 int matchMSA128RegisterName(StringRef Name);
297
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000298 int matchMSA128CtrlRegisterName(StringRef Name);
299
Jack Carterd0bd6422013-04-18 00:41:53 +0000300 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000301
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000302 unsigned getGPR(int RegNo);
303
Toma Tabacu89a712b2015-04-15 10:48:56 +0000304 /// Returns the internal register number for the current AT. Also checks if
305 /// the current AT is unavailable (set to $0) and gives an error if it is.
306 /// This should be used in pseudo-instruction expansions which need AT.
307 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000308
309 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000310 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000311
312 // Helper function that checks if the value of a vector index is within the
313 // boundaries of accepted values for each RegisterKind
314 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
315 bool validateMSAIndex(int Val, int RegKind);
316
Daniel Sandersf0df2212014-08-04 12:20:00 +0000317 // Selects a new architecture by updating the FeatureBits with the necessary
318 // info including implied dependencies.
319 // Internally, it clears all the feature bits related to *any* architecture
320 // and selects the new one using the ToggleFeature functionality of the
321 // MCSubtargetInfo object that handles implied dependencies. The reason we
322 // clear all the arch related bits manually is because ToggleFeature only
323 // clears the features that imply the feature being cleared and not the
324 // features implied by the feature being cleared. This is easier to see
325 // with an example:
326 // --------------------------------------------------
327 // | Feature | Implies |
328 // | -------------------------------------------------|
329 // | FeatureMips1 | None |
330 // | FeatureMips2 | FeatureMips1 |
331 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
332 // | FeatureMips4 | FeatureMips3 |
333 // | ... | |
334 // --------------------------------------------------
335 //
336 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
337 // FeatureMipsGP64 | FeatureMips1)
338 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
339 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000340 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000341 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
342 STI.setFeatureBits(FeatureBits);
343 setAvailableFeatures(
344 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000345 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000346 }
347
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000348 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000349 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000350 setAvailableFeatures(
351 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000352 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000353 }
354 }
355
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000356 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000357 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000358 setAvailableFeatures(
359 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000360 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000361 }
362 }
363
Rafael Espindola870c4e92012-01-11 03:56:41 +0000364public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000365 enum MipsMatchResultTy {
366 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
367#define GET_OPERAND_DIAGNOSTIC_TYPES
368#include "MipsGenAsmMatcher.inc"
369#undef GET_OPERAND_DIAGNOSTIC_TYPES
370
371 };
372
Joey Gouly0e76fa72013-09-12 10:28:05 +0000373 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000374 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000375 : MCTargetAsmParser(), STI(sti),
376 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
377 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000378 MCAsmParserExtension::Initialize(parser);
379
Toma Tabacu11e14a92015-04-21 11:50:52 +0000380 parser.addAliasForDirective(".asciiz", ".asciz");
381
Jack Carterb4dbc172012-09-05 23:34:03 +0000382 // Initialize the set of available features.
383 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000384
385 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000386 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000387 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000388
389 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000390 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000391 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000392
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000393 getTargetStreamer().updateABIInfo(*this);
394
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000395 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000396 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000397
398 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000399
400 Triple TheTriple(sti.getTargetTriple());
401 if ((TheTriple.getArch() == Triple::mips) ||
402 (TheTriple.getArch() == Triple::mips64))
403 IsLittleEndian = false;
404 else
405 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000406 }
407
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000408 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
409 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
410
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000411 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
412 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000413 const MipsABIInfo &getABI() const { return ABI; }
414 bool isABI_N32() const { return ABI.IsN32(); }
415 bool isABI_N64() const { return ABI.IsN64(); }
416 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000417 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000418
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000419 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000420 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000421 }
422
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000424 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000425 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000426 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
427 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
428 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
429 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
430 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000431 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000432 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433 }
434 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000435 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000436 }
437 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000438 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000439 }
440 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000441 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000442 }
Daniel Sanders17793142015-02-18 16:24:50 +0000443 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000444 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000445 }
446 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000447 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000448 }
449 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000451 }
452 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000453 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000454 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000456 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000457 }
458 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000459 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000461
462 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
463 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
464 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000465 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000467 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000468
469 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000470 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000471 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000472
Eric Christophere8ae3e32015-05-07 23:10:21 +0000473 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000474 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000475 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476
Toma Tabacud9d344b2015-04-27 14:05:04 +0000477 /// Warn if RegIndex is the same as the current AT.
478 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000479
480 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000481
482 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000483};
484}
485
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000486namespace {
487
488/// MipsOperand - Instances of this class represent a parsed Mips machine
489/// instruction.
490class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000491public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000492 /// Broad categories of register classes
493 /// The exact class is finalized by the render method.
494 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000495 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000496 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000498 RegKind_FCC = 4, /// FCC
499 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
500 RegKind_MSACtrl = 16, /// MSA control registers
501 RegKind_COP2 = 32, /// COP2
502 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
503 /// context).
504 RegKind_CCR = 128, /// CCR
505 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000506 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000507 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000508 /// Potentially any (e.g. $1)
509 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
510 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000511 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000512 };
513
514private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000515 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000516 k_Immediate, /// An immediate (possibly involving symbol references)
517 k_Memory, /// Base + Offset Memory Address
518 k_PhysRegister, /// A physical register from the Mips namespace
519 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000520 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000521 k_RegList, /// A physical register list
522 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000523 } Kind;
524
David Blaikie960ea3f2014-06-08 16:18:35 +0000525public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000526 MipsOperand(KindTy K, MipsAsmParser &Parser)
527 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
528
David Blaikie960ea3f2014-06-08 16:18:35 +0000529private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000530 /// For diagnostics, and checking the assembler temporary
531 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000532
Eric Christopher8996c5d2013-03-15 00:42:55 +0000533 struct Token {
534 const char *Data;
535 unsigned Length;
536 };
537
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000538 struct PhysRegOp {
539 unsigned Num; /// Register Number
540 };
541
542 struct RegIdxOp {
543 unsigned Index; /// Index into the register class
544 RegKind Kind; /// Bitfield of the kinds it could possibly be
545 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000546 };
547
548 struct ImmOp {
549 const MCExpr *Val;
550 };
551
552 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000553 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000554 const MCExpr *Off;
555 };
556
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000557 struct RegListOp {
558 SmallVector<unsigned, 10> *List;
559 };
560
Jack Carterb4dbc172012-09-05 23:34:03 +0000561 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000562 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000563 struct PhysRegOp PhysReg;
564 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000565 struct ImmOp Imm;
566 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000567 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000568 };
569
570 SMLoc StartLoc, EndLoc;
571
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000572 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000573 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
574 const MCRegisterInfo *RegInfo,
575 SMLoc S, SMLoc E,
576 MipsAsmParser &Parser) {
577 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000578 Op->RegIdx.Index = Index;
579 Op->RegIdx.RegInfo = RegInfo;
580 Op->RegIdx.Kind = RegKind;
581 Op->StartLoc = S;
582 Op->EndLoc = E;
583 return Op;
584 }
585
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000586public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000587 /// Coerce the register to GPR32 and return the real register for the current
588 /// target.
589 unsigned getGPR32Reg() const {
590 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000591 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000592 unsigned ClassID = Mips::GPR32RegClassID;
593 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000594 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000595
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000596 /// Coerce the register to GPR32 and return the real register for the current
597 /// target.
598 unsigned getGPRMM16Reg() const {
599 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
600 unsigned ClassID = Mips::GPR32RegClassID;
601 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
602 }
603
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 /// Coerce the register to GPR64 and return the real register for the current
605 /// target.
606 unsigned getGPR64Reg() const {
607 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
608 unsigned ClassID = Mips::GPR64RegClassID;
609 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000610 }
611
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000612private:
613 /// Coerce the register to AFGR64 and return the real register for the current
614 /// target.
615 unsigned getAFGR64Reg() const {
616 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
617 if (RegIdx.Index % 2 != 0)
618 AsmParser.Warning(StartLoc, "Float register should be even.");
619 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
620 .getRegister(RegIdx.Index / 2);
621 }
622
623 /// Coerce the register to FGR64 and return the real register for the current
624 /// target.
625 unsigned getFGR64Reg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
627 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
628 .getRegister(RegIdx.Index);
629 }
630
631 /// Coerce the register to FGR32 and return the real register for the current
632 /// target.
633 unsigned getFGR32Reg() const {
634 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
635 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
636 .getRegister(RegIdx.Index);
637 }
638
639 /// Coerce the register to FGRH32 and return the real register for the current
640 /// target.
641 unsigned getFGRH32Reg() const {
642 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
643 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
644 .getRegister(RegIdx.Index);
645 }
646
647 /// Coerce the register to FCC and return the real register for the current
648 /// target.
649 unsigned getFCCReg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
651 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
652 .getRegister(RegIdx.Index);
653 }
654
655 /// Coerce the register to MSA128 and return the real register for the current
656 /// target.
657 unsigned getMSA128Reg() const {
658 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
659 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
660 // identical
661 unsigned ClassID = Mips::MSA128BRegClassID;
662 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to MSACtrl and return the real register for the
666 /// current target.
667 unsigned getMSACtrlReg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
669 unsigned ClassID = Mips::MSACtrlRegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
671 }
672
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000673 /// Coerce the register to COP0 and return the real register for the
674 /// current target.
675 unsigned getCOP0Reg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
677 unsigned ClassID = Mips::COP0RegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
679 }
680
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000681 /// Coerce the register to COP2 and return the real register for the
682 /// current target.
683 unsigned getCOP2Reg() const {
684 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
685 unsigned ClassID = Mips::COP2RegClassID;
686 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
687 }
688
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000689 /// Coerce the register to COP3 and return the real register for the
690 /// current target.
691 unsigned getCOP3Reg() const {
692 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
693 unsigned ClassID = Mips::COP3RegClassID;
694 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
695 }
696
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000697 /// Coerce the register to ACC64DSP and return the real register for the
698 /// current target.
699 unsigned getACC64DSPReg() const {
700 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
701 unsigned ClassID = Mips::ACC64DSPRegClassID;
702 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
703 }
704
705 /// Coerce the register to HI32DSP and return the real register for the
706 /// current target.
707 unsigned getHI32DSPReg() const {
708 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
709 unsigned ClassID = Mips::HI32DSPRegClassID;
710 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
711 }
712
713 /// Coerce the register to LO32DSP and return the real register for the
714 /// current target.
715 unsigned getLO32DSPReg() const {
716 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
717 unsigned ClassID = Mips::LO32DSPRegClassID;
718 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
719 }
720
721 /// Coerce the register to CCR and return the real register for the
722 /// current target.
723 unsigned getCCRReg() const {
724 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
725 unsigned ClassID = Mips::CCRRegClassID;
726 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
727 }
728
729 /// Coerce the register to HWRegs and return the real register for the
730 /// current target.
731 unsigned getHWRegsReg() const {
732 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
733 unsigned ClassID = Mips::HWRegsRegClassID;
734 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
735 }
736
737public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000738 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000739 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000740 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000741 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000742 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000743 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000744 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000745 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000746 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000747
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000748 void addRegOperands(MCInst &Inst, unsigned N) const {
749 llvm_unreachable("Use a custom parser instead");
750 }
751
Daniel Sanders21bce302014-04-01 12:35:23 +0000752 /// Render the operand to an MCInst as a GPR32
753 /// Asserts if the wrong number of operands are requested, or the operand
754 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
756 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000757 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000758 }
759
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000760 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
761 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000762 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000763 }
764
Jozef Kolek1904fa22014-11-24 14:25:53 +0000765 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
766 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000767 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000768 }
769
Zoran Jovanovic41688672015-02-10 16:36:20 +0000770 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
771 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000772 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000773 }
774
Daniel Sanders21bce302014-04-01 12:35:23 +0000775 /// Render the operand to an MCInst as a GPR64
776 /// Asserts if the wrong number of operands are requested, or the operand
777 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
779 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000780 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 }
782
783 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
784 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000785 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 }
787
788 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000790 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 }
792
793 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
794 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000795 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000796 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000797 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000798 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
799 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 }
801
802 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
803 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000804 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 }
806
807 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
808 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000809 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 }
811
812 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
813 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 }
816
817 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
818 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 }
821
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000822 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 1 && "Invalid number of operands!");
824 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
825 }
826
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000829 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000832 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000835 }
836
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 }
841
842 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 }
846
847 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
852 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000854 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 }
856
857 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000862 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000863 assert(N == 1 && "Invalid number of operands!");
864 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000865 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000866 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000867
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000868 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000869 assert(N == 2 && "Invalid number of operands!");
870
Jim Grosbache9119e42015-05-13 18:37:00 +0000871 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000872
873 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000874 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000875 }
876
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000877 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
878 assert(N == 2 && "Invalid number of operands!");
879
Jim Grosbache9119e42015-05-13 18:37:00 +0000880 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000881
882 const MCExpr *Expr = getMemOff();
883 addExpr(Inst, Expr);
884 }
885
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000886 void addRegListOperands(MCInst &Inst, unsigned N) const {
887 assert(N == 1 && "Invalid number of operands!");
888
889 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000890 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000891 }
892
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000893 void addRegPairOperands(MCInst &Inst, unsigned N) const {
894 assert(N == 2 && "Invalid number of operands!");
895 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000896 Inst.addOperand(MCOperand::createReg(RegNo++));
897 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000898 }
899
Zoran Jovanovic41688672015-02-10 16:36:20 +0000900 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
901 assert(N == 2 && "Invalid number of operands!");
902 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000903 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000904 }
905
Craig Topper56c590a2014-04-29 07:58:02 +0000906 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000907 // As a special case until we sort out the definition of div/divu, pretend
908 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
909 if (isGPRAsmReg() && RegIdx.Index == 0)
910 return true;
911
912 return Kind == k_PhysRegister;
913 }
914 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000915 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000916 bool isConstantImm() const {
917 return isImm() && dyn_cast<MCConstantExpr>(getImm());
918 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000919 template <unsigned Bits> bool isUImm() const {
920 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
921 }
Craig Topper56c590a2014-04-29 07:58:02 +0000922 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 // Note: It's not possible to pretend that other operand kinds are tokens.
924 // The matcher emitter checks tokens first.
925 return Kind == k_Token;
926 }
Craig Topper56c590a2014-04-29 07:58:02 +0000927 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000928 bool isConstantMemOff() const {
929 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
930 }
931 template <unsigned Bits> bool isMemWithSimmOffset() const {
932 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
933 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000934 bool isMemWithGRPMM16Base() const {
935 return isMem() && getMemBase()->isMM16AsmReg();
936 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000937 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
938 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
939 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
940 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000941 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
942 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
943 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
944 && (getMemBase()->getGPR32Reg() == Mips::SP);
945 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000946 bool isRegList16() const {
947 if (!isRegList())
948 return false;
949
950 int Size = RegList.List->size();
951 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
952 RegList.List->back() != Mips::RA)
953 return false;
954
955 int PrevReg = *RegList.List->begin();
956 for (int i = 1; i < Size - 1; i++) {
957 int Reg = (*(RegList.List))[i];
958 if ( Reg != PrevReg + 1)
959 return false;
960 PrevReg = Reg;
961 }
962
963 return true;
964 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000965 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000966 bool isLSAImm() const {
967 if (!isConstantImm())
968 return false;
969 int64_t Val = getConstantImm();
970 return 1 <= Val && Val <= 4;
971 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000972 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000973 bool isMovePRegPair() const {
974 if (Kind != k_RegList || RegList.List->size() != 2)
975 return false;
976
977 unsigned R0 = RegList.List->front();
978 unsigned R1 = RegList.List->back();
979
980 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
981 (R0 == Mips::A1 && R1 == Mips::A3) ||
982 (R0 == Mips::A2 && R1 == Mips::A3) ||
983 (R0 == Mips::A0 && R1 == Mips::S5) ||
984 (R0 == Mips::A0 && R1 == Mips::S6) ||
985 (R0 == Mips::A0 && R1 == Mips::A1) ||
986 (R0 == Mips::A0 && R1 == Mips::A2) ||
987 (R0 == Mips::A0 && R1 == Mips::A3))
988 return true;
989
990 return false;
991 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000992
993 StringRef getToken() const {
994 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000995 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000996 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000997 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000998
Craig Topper56c590a2014-04-29 07:58:02 +0000999 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 // As a special case until we sort out the definition of div/divu, pretend
1001 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1002 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1003 RegIdx.Kind & RegKind_GPR)
1004 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001005
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 assert(Kind == k_PhysRegister && "Invalid access!");
1007 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001008 }
1009
Jack Carterb4dbc172012-09-05 23:34:03 +00001010 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001012 return Imm.Val;
1013 }
1014
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 int64_t getConstantImm() const {
1016 const MCExpr *Val = getImm();
1017 return static_cast<const MCConstantExpr *>(Val)->getValue();
1018 }
1019
1020 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001021 assert((Kind == k_Memory) && "Invalid access!");
1022 return Mem.Base;
1023 }
1024
1025 const MCExpr *getMemOff() const {
1026 assert((Kind == k_Memory) && "Invalid access!");
1027 return Mem.Off;
1028 }
1029
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001030 int64_t getConstantMemOff() const {
1031 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1032 }
1033
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001034 const SmallVectorImpl<unsigned> &getRegList() const {
1035 assert((Kind == k_RegList) && "Invalid access!");
1036 return *(RegList.List);
1037 }
1038
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001039 unsigned getRegPair() const {
1040 assert((Kind == k_RegPair) && "Invalid access!");
1041 return RegIdx.Index;
1042 }
1043
David Blaikie960ea3f2014-06-08 16:18:35 +00001044 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1045 MipsAsmParser &Parser) {
1046 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001047 Op->Tok.Data = Str.data();
1048 Op->Tok.Length = Str.size();
1049 Op->StartLoc = S;
1050 Op->EndLoc = S;
1051 return Op;
1052 }
1053
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001054 /// Create a numeric register (e.g. $1). The exact register remains
1055 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001056 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001057 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001058 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001059 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001061 }
1062
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001063 /// Create a register that is definitely a GPR.
1064 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001065 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001066 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001067 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001069 }
1070
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 /// Create a register that is definitely a FGR.
1072 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001073 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001074 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001075 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001076 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1077 }
1078
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001079 /// Create a register that is definitely a HWReg.
1080 /// This is typically only used for named registers such as $hwr_cpunum.
1081 static std::unique_ptr<MipsOperand>
1082 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1083 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1084 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1085 }
1086
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001087 /// Create a register that is definitely an FCC.
1088 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001089 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001090 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001091 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1093 }
1094
1095 /// Create a register that is definitely an ACC.
1096 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001097 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001098 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1101 }
1102
1103 /// Create a register that is definitely an MSA128.
1104 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001105 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001106 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001107 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1109 }
1110
1111 /// Create a register that is definitely an MSACtrl.
1112 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001113 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001114 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001115 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1117 }
1118
David Blaikie960ea3f2014-06-08 16:18:35 +00001119 static std::unique_ptr<MipsOperand>
1120 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1121 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001122 Op->Imm.Val = Val;
1123 Op->StartLoc = S;
1124 Op->EndLoc = E;
1125 return Op;
1126 }
1127
David Blaikie960ea3f2014-06-08 16:18:35 +00001128 static std::unique_ptr<MipsOperand>
1129 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1130 SMLoc E, MipsAsmParser &Parser) {
1131 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1132 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001133 Op->Mem.Off = Off;
1134 Op->StartLoc = S;
1135 Op->EndLoc = E;
1136 return Op;
1137 }
1138
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001139 static std::unique_ptr<MipsOperand>
1140 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1141 MipsAsmParser &Parser) {
1142 assert (Regs.size() > 0 && "Empty list not allowed");
1143
1144 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001145 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001146 Op->StartLoc = StartLoc;
1147 Op->EndLoc = EndLoc;
1148 return Op;
1149 }
1150
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001151 static std::unique_ptr<MipsOperand>
1152 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1153 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1154 Op->RegIdx.Index = RegNo;
1155 Op->StartLoc = S;
1156 Op->EndLoc = E;
1157 return Op;
1158 }
1159
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001160 bool isGPRAsmReg() const {
1161 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001162 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001163 bool isMM16AsmReg() const {
1164 if (!(isRegIdx() && RegIdx.Kind))
1165 return false;
1166 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1167 || RegIdx.Index == 16 || RegIdx.Index == 17);
1168 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001169 bool isMM16AsmRegZero() const {
1170 if (!(isRegIdx() && RegIdx.Kind))
1171 return false;
1172 return (RegIdx.Index == 0 ||
1173 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1174 RegIdx.Index == 17);
1175 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001176 bool isMM16AsmRegMoveP() const {
1177 if (!(isRegIdx() && RegIdx.Kind))
1178 return false;
1179 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1180 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1181 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001182 bool isFGRAsmReg() const {
1183 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1184 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001185 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001186 bool isHWRegsAsmReg() const {
1187 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001188 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001189 bool isCCRAsmReg() const {
1190 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001191 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001193 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1194 return false;
1195 if (!AsmParser.hasEightFccRegisters())
1196 return RegIdx.Index == 0;
1197 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001198 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001199 bool isACCAsmReg() const {
1200 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001201 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001202 bool isCOP0AsmReg() const {
1203 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1204 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001205 bool isCOP2AsmReg() const {
1206 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001207 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001208 bool isCOP3AsmReg() const {
1209 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1210 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001211 bool isMSA128AsmReg() const {
1212 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001213 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001214 bool isMSACtrlAsmReg() const {
1215 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001216 }
1217
Jack Carterb4dbc172012-09-05 23:34:03 +00001218 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001219 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001220 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001221 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001222
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001223 virtual ~MipsOperand() {
1224 switch (Kind) {
1225 case k_Immediate:
1226 break;
1227 case k_Memory:
1228 delete Mem.Base;
1229 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001230 case k_RegList:
1231 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001232 case k_PhysRegister:
1233 case k_RegisterIndex:
1234 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001235 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001236 break;
1237 }
1238 }
1239
Craig Topper56c590a2014-04-29 07:58:02 +00001240 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001241 switch (Kind) {
1242 case k_Immediate:
1243 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001244 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 OS << ">";
1246 break;
1247 case k_Memory:
1248 OS << "Mem<";
1249 Mem.Base->print(OS);
1250 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001251 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001252 OS << ">";
1253 break;
1254 case k_PhysRegister:
1255 OS << "PhysReg<" << PhysReg.Num << ">";
1256 break;
1257 case k_RegisterIndex:
1258 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1259 break;
1260 case k_Token:
1261 OS << Tok.Data;
1262 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001263 case k_RegList:
1264 OS << "RegList< ";
1265 for (auto Reg : (*RegList.List))
1266 OS << Reg << " ";
1267 OS << ">";
1268 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001269 case k_RegPair:
1270 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1271 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001272 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001273 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001274}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001275} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001276
Jack Carter9e65aa32013-03-22 00:05:30 +00001277namespace llvm {
1278extern const MCInstrDesc MipsInsts[];
1279}
1280static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1281 return MipsInsts[Opcode];
1282}
1283
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001284static bool hasShortDelaySlot(unsigned Opcode) {
1285 switch (Opcode) {
1286 case Mips::JALS_MM:
1287 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001288 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001289 case Mips::BGEZALS_MM:
1290 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001291 return true;
1292 default:
1293 return false;
1294 }
1295}
1296
Jack Carter9e65aa32013-03-22 00:05:30 +00001297bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001298 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001299 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001300
Jack Carter9e65aa32013-03-22 00:05:30 +00001301 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001302
1303 if (MCID.isBranch() || MCID.isCall()) {
1304 const unsigned Opcode = Inst.getOpcode();
1305 MCOperand Offset;
1306
1307 switch (Opcode) {
1308 default:
1309 break;
Kai Nackee0245392015-01-27 19:11:28 +00001310 case Mips::BBIT0:
1311 case Mips::BBIT032:
1312 case Mips::BBIT1:
1313 case Mips::BBIT132:
1314 assert(hasCnMips() && "instruction only valid for octeon cpus");
1315 // Fall through
1316
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001317 case Mips::BEQ:
1318 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001319 case Mips::BEQ_MM:
1320 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001321 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001322 Offset = Inst.getOperand(2);
1323 if (!Offset.isImm())
1324 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001325 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001326 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001327 if (OffsetToAlignment(Offset.getImm(),
1328 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001329 return Error(IDLoc, "branch to misaligned address");
1330 break;
1331 case Mips::BGEZ:
1332 case Mips::BGTZ:
1333 case Mips::BLEZ:
1334 case Mips::BLTZ:
1335 case Mips::BGEZAL:
1336 case Mips::BLTZAL:
1337 case Mips::BC1F:
1338 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001339 case Mips::BGEZ_MM:
1340 case Mips::BGTZ_MM:
1341 case Mips::BLEZ_MM:
1342 case Mips::BLTZ_MM:
1343 case Mips::BGEZAL_MM:
1344 case Mips::BLTZAL_MM:
1345 case Mips::BC1F_MM:
1346 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001347 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001348 Offset = Inst.getOperand(1);
1349 if (!Offset.isImm())
1350 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001351 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001352 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001353 if (OffsetToAlignment(Offset.getImm(),
1354 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001355 return Error(IDLoc, "branch to misaligned address");
1356 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001357 case Mips::BEQZ16_MM:
1358 case Mips::BNEZ16_MM:
1359 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1360 Offset = Inst.getOperand(1);
1361 if (!Offset.isImm())
1362 break; // We'll deal with this situation later on when applying fixups.
1363 if (!isIntN(8, Offset.getImm()))
1364 return Error(IDLoc, "branch target out of range");
1365 if (OffsetToAlignment(Offset.getImm(), 2LL))
1366 return Error(IDLoc, "branch to misaligned address");
1367 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001368 }
1369 }
1370
Daniel Sandersa84989a2014-06-16 13:25:35 +00001371 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1372 // We still accept it but it is a normal nop.
1373 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1374 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1375 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1376 "nop instruction");
1377 }
1378
Kai Nackee0245392015-01-27 19:11:28 +00001379 if (hasCnMips()) {
1380 const unsigned Opcode = Inst.getOpcode();
1381 MCOperand Opnd;
1382 int Imm;
1383
1384 switch (Opcode) {
1385 default:
1386 break;
1387
1388 case Mips::BBIT0:
1389 case Mips::BBIT032:
1390 case Mips::BBIT1:
1391 case Mips::BBIT132:
1392 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1393 // The offset is handled above
1394 Opnd = Inst.getOperand(1);
1395 if (!Opnd.isImm())
1396 return Error(IDLoc, "expected immediate operand kind");
1397 Imm = Opnd.getImm();
1398 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1399 Opcode == Mips::BBIT1 ? 63 : 31))
1400 return Error(IDLoc, "immediate operand value out of range");
1401 if (Imm > 31) {
1402 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1403 : Mips::BBIT132);
1404 Inst.getOperand(1).setImm(Imm - 32);
1405 }
1406 break;
1407
1408 case Mips::CINS:
1409 case Mips::CINS32:
1410 case Mips::EXTS:
1411 case Mips::EXTS32:
1412 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1413 // Check length
1414 Opnd = Inst.getOperand(3);
1415 if (!Opnd.isImm())
1416 return Error(IDLoc, "expected immediate operand kind");
1417 Imm = Opnd.getImm();
1418 if (Imm < 0 || Imm > 31)
1419 return Error(IDLoc, "immediate operand value out of range");
1420 // Check position
1421 Opnd = Inst.getOperand(2);
1422 if (!Opnd.isImm())
1423 return Error(IDLoc, "expected immediate operand kind");
1424 Imm = Opnd.getImm();
1425 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1426 Opcode == Mips::EXTS ? 63 : 31))
1427 return Error(IDLoc, "immediate operand value out of range");
1428 if (Imm > 31) {
1429 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1430 Inst.getOperand(2).setImm(Imm - 32);
1431 }
1432 break;
1433
1434 case Mips::SEQi:
1435 case Mips::SNEi:
1436 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1437 Opnd = Inst.getOperand(2);
1438 if (!Opnd.isImm())
1439 return Error(IDLoc, "expected immediate operand kind");
1440 Imm = Opnd.getImm();
1441 if (!isInt<10>(Imm))
1442 return Error(IDLoc, "immediate operand value out of range");
1443 break;
1444 }
1445 }
1446
Jack Carter9e65aa32013-03-22 00:05:30 +00001447 if (MCID.mayLoad() || MCID.mayStore()) {
1448 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001449 // reference or immediate we may have to expand instructions.
1450 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001451 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001452 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1453 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001454 MCOperand &Op = Inst.getOperand(i);
1455 if (Op.isImm()) {
1456 int MemOffset = Op.getImm();
1457 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001458 // Offset can't exceed 16bit value.
1459 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001460 return false;
1461 }
1462 } else if (Op.isExpr()) {
1463 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001465 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001466 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001467 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001468 // Expand symbol.
1469 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001470 return false;
1471 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001472 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001473 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001474 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001475 }
1476 }
1477 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001478 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001479 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001480
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001481 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001482 if (MCID.mayLoad()) {
1483 // Try to create 16-bit GP relative load instruction.
1484 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1485 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1486 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1487 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1488 MCOperand &Op = Inst.getOperand(i);
1489 if (Op.isImm()) {
1490 int MemOffset = Op.getImm();
1491 MCOperand &DstReg = Inst.getOperand(0);
1492 MCOperand &BaseReg = Inst.getOperand(1);
1493 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1494 getContext().getRegisterInfo()->getRegClass(
1495 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1496 BaseReg.getReg() == Mips::GP) {
1497 MCInst TmpInst;
1498 TmpInst.setLoc(IDLoc);
1499 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001500 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1501 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1502 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001503 Instructions.push_back(TmpInst);
1504 return false;
1505 }
1506 }
1507 }
1508 } // for
1509 } // if load
1510
1511 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1512
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001513 MCOperand Opnd;
1514 int Imm;
1515
1516 switch (Inst.getOpcode()) {
1517 default:
1518 break;
1519 case Mips::ADDIUS5_MM:
1520 Opnd = Inst.getOperand(2);
1521 if (!Opnd.isImm())
1522 return Error(IDLoc, "expected immediate operand kind");
1523 Imm = Opnd.getImm();
1524 if (Imm < -8 || Imm > 7)
1525 return Error(IDLoc, "immediate operand value out of range");
1526 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001527 case Mips::ADDIUSP_MM:
1528 Opnd = Inst.getOperand(0);
1529 if (!Opnd.isImm())
1530 return Error(IDLoc, "expected immediate operand kind");
1531 Imm = Opnd.getImm();
1532 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1533 Imm % 4 != 0)
1534 return Error(IDLoc, "immediate operand value out of range");
1535 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001536 case Mips::SLL16_MM:
1537 case Mips::SRL16_MM:
1538 Opnd = Inst.getOperand(2);
1539 if (!Opnd.isImm())
1540 return Error(IDLoc, "expected immediate operand kind");
1541 Imm = Opnd.getImm();
1542 if (Imm < 1 || Imm > 8)
1543 return Error(IDLoc, "immediate operand value out of range");
1544 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001545 case Mips::LI16_MM:
1546 Opnd = Inst.getOperand(1);
1547 if (!Opnd.isImm())
1548 return Error(IDLoc, "expected immediate operand kind");
1549 Imm = Opnd.getImm();
1550 if (Imm < -1 || Imm > 126)
1551 return Error(IDLoc, "immediate operand value out of range");
1552 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001553 case Mips::ADDIUR2_MM:
1554 Opnd = Inst.getOperand(2);
1555 if (!Opnd.isImm())
1556 return Error(IDLoc, "expected immediate operand kind");
1557 Imm = Opnd.getImm();
1558 if (!(Imm == 1 || Imm == -1 ||
1559 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1560 return Error(IDLoc, "immediate operand value out of range");
1561 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001562 case Mips::ADDIUR1SP_MM:
1563 Opnd = Inst.getOperand(1);
1564 if (!Opnd.isImm())
1565 return Error(IDLoc, "expected immediate operand kind");
1566 Imm = Opnd.getImm();
1567 if (OffsetToAlignment(Imm, 4LL))
1568 return Error(IDLoc, "misaligned immediate operand value");
1569 if (Imm < 0 || Imm > 255)
1570 return Error(IDLoc, "immediate operand value out of range");
1571 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001572 case Mips::ANDI16_MM:
1573 Opnd = Inst.getOperand(2);
1574 if (!Opnd.isImm())
1575 return Error(IDLoc, "expected immediate operand kind");
1576 Imm = Opnd.getImm();
1577 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1578 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1579 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1580 return Error(IDLoc, "immediate operand value out of range");
1581 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001582 case Mips::LBU16_MM:
1583 Opnd = Inst.getOperand(2);
1584 if (!Opnd.isImm())
1585 return Error(IDLoc, "expected immediate operand kind");
1586 Imm = Opnd.getImm();
1587 if (Imm < -1 || Imm > 14)
1588 return Error(IDLoc, "immediate operand value out of range");
1589 break;
1590 case Mips::SB16_MM:
1591 Opnd = Inst.getOperand(2);
1592 if (!Opnd.isImm())
1593 return Error(IDLoc, "expected immediate operand kind");
1594 Imm = Opnd.getImm();
1595 if (Imm < 0 || Imm > 15)
1596 return Error(IDLoc, "immediate operand value out of range");
1597 break;
1598 case Mips::LHU16_MM:
1599 case Mips::SH16_MM:
1600 Opnd = Inst.getOperand(2);
1601 if (!Opnd.isImm())
1602 return Error(IDLoc, "expected immediate operand kind");
1603 Imm = Opnd.getImm();
1604 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1605 return Error(IDLoc, "immediate operand value out of range");
1606 break;
1607 case Mips::LW16_MM:
1608 case Mips::SW16_MM:
1609 Opnd = Inst.getOperand(2);
1610 if (!Opnd.isImm())
1611 return Error(IDLoc, "expected immediate operand kind");
1612 Imm = Opnd.getImm();
1613 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1614 return Error(IDLoc, "immediate operand value out of range");
1615 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001616 case Mips::CACHE:
1617 case Mips::PREF:
1618 Opnd = Inst.getOperand(2);
1619 if (!Opnd.isImm())
1620 return Error(IDLoc, "expected immediate operand kind");
1621 Imm = Opnd.getImm();
1622 if (!isUInt<5>(Imm))
1623 return Error(IDLoc, "immediate operand value out of range");
1624 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001625 case Mips::ADDIUPC_MM:
1626 MCOperand Opnd = Inst.getOperand(1);
1627 if (!Opnd.isImm())
1628 return Error(IDLoc, "expected immediate operand kind");
1629 int Imm = Opnd.getImm();
1630 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1631 return Error(IDLoc, "immediate operand value out of range");
1632 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001633 }
1634 }
1635
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001636 if (needsExpansion(Inst)) {
1637 if (expandInstruction(Inst, IDLoc, Instructions))
1638 return true;
1639 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001640 Instructions.push_back(Inst);
1641
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001642 // If this instruction has a delay slot and .set reorder is active,
1643 // emit a NOP after it.
1644 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1645 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1646
Jack Carter9e65aa32013-03-22 00:05:30 +00001647 return false;
1648}
1649
Jack Carter30a59822012-10-04 04:03:53 +00001650bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1651
Jack Carterd0bd6422013-04-18 00:41:53 +00001652 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001653 case Mips::LoadImm32:
1654 case Mips::LoadImm64:
1655 case Mips::LoadAddrImm32:
1656 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001657 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001658 case Mips::LWM_MM:
1659 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001660 case Mips::JalOneReg:
1661 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001662 case Mips::BneImm:
1663 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001664 case Mips::BLT:
1665 case Mips::BLE:
1666 case Mips::BGE:
1667 case Mips::BGT:
1668 case Mips::BLTU:
1669 case Mips::BLEU:
1670 case Mips::BGEU:
1671 case Mips::BGTU:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001672 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001673 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001674 return true;
1675 default:
1676 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001677 }
1678}
Jack Carter92995f12012-10-06 00:53:28 +00001679
Matheus Almeida3813d572014-06-19 14:39:14 +00001680bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001681 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001682 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001683 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001684 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001685 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001686 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001687 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001688 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001689 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001690 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001691 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001692 case Mips::B_MM_Pseudo:
1693 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001694 case Mips::SWM_MM:
1695 case Mips::LWM_MM:
1696 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001697 case Mips::JalOneReg:
1698 case Mips::JalTwoReg:
1699 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001700 case Mips::BneImm:
1701 case Mips::BeqImm:
1702 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001703 case Mips::BLT:
1704 case Mips::BLE:
1705 case Mips::BGE:
1706 case Mips::BGT:
1707 case Mips::BLTU:
1708 case Mips::BLEU:
1709 case Mips::BGEU:
1710 case Mips::BGTU:
1711 return expandCondBranches(Inst, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001712 case Mips::Ulhu:
1713 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001714 case Mips::Ulw:
1715 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 }
Jack Carter30a59822012-10-04 04:03:53 +00001717}
Jack Carter92995f12012-10-06 00:53:28 +00001718
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001719namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001720template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001721void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001722 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001723 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001724 if (ShiftAmount >= 32) {
1725 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001726 tmpInst.addOperand(MCOperand::createReg(RegNo));
1727 tmpInst.addOperand(MCOperand::createReg(RegNo));
1728 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001729 tmpInst.setLoc(IDLoc);
1730 Instructions.push_back(tmpInst);
1731 tmpInst.clear();
1732 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001733 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001734 tmpInst.addOperand(MCOperand::createReg(RegNo));
1735 tmpInst.addOperand(MCOperand::createReg(RegNo));
1736 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001737 tmpInst.setLoc(IDLoc);
1738 Instructions.push_back(tmpInst);
1739 tmpInst.clear();
1740 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001741 // There's no need for an ORi if the immediate is 0.
1742 if (Operand.isImm() && Operand.getImm() == 0)
1743 return;
1744
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001745 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001746 tmpInst.addOperand(MCOperand::createReg(RegNo));
1747 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001748 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001749 tmpInst.setLoc(IDLoc);
1750 Instructions.push_back(tmpInst);
1751}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001752
Toma Tabacua2861db2015-05-01 10:26:47 +00001753template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001754void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001755 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001756 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001757 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001758}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001759}
1760
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001761bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1762 SmallVectorImpl<MCInst> &Instructions) {
1763 // Create a JALR instruction which is going to replace the pseudo-JAL.
1764 MCInst JalrInst;
1765 JalrInst.setLoc(IDLoc);
1766 const MCOperand FirstRegOp = Inst.getOperand(0);
1767 const unsigned Opcode = Inst.getOpcode();
1768
1769 if (Opcode == Mips::JalOneReg) {
1770 // jal $rs => jalr $rs
1771 if (inMicroMipsMode()) {
1772 JalrInst.setOpcode(Mips::JALR16_MM);
1773 JalrInst.addOperand(FirstRegOp);
1774 } else {
1775 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001776 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001777 JalrInst.addOperand(FirstRegOp);
1778 }
1779 } else if (Opcode == Mips::JalTwoReg) {
1780 // jal $rd, $rs => jalr $rd, $rs
1781 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1782 JalrInst.addOperand(FirstRegOp);
1783 const MCOperand SecondRegOp = Inst.getOperand(1);
1784 JalrInst.addOperand(SecondRegOp);
1785 }
1786 Instructions.push_back(JalrInst);
1787
1788 // If .set reorder is active, emit a NOP after it.
1789 if (AssemblerOptions.back()->isReorder()) {
1790 // This is a 32-bit NOP because these 2 pseudo-instructions
1791 // do not have a short delay slot.
1792 MCInst NopInst;
1793 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001794 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1795 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1796 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001797 Instructions.push_back(NopInst);
1798 }
1799
1800 return false;
1801}
1802
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001803bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1804 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001805 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001806 if (!Is32BitImm && !isGP64bit()) {
1807 Error(IDLoc, "instruction requires a 64-bit architecture");
1808 return true;
1809 }
1810
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001811 bool UseSrcReg = false;
1812 if (SrcReg != Mips::NoRegister)
1813 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001814
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001815 MCInst tmpInst;
1816
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001817 unsigned TmpReg = DstReg;
1818 if (UseSrcReg && (DstReg == SrcReg)) {
1819 // At this point we need AT to perform the expansions and we exit if it is
1820 // not available.
1821 unsigned ATReg = getATReg(IDLoc);
1822 if (!ATReg)
1823 return true;
1824 TmpReg = ATReg;
1825 }
1826
Jack Carter92995f12012-10-06 00:53:28 +00001827 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001828 // FIXME: gas has a special case for values that are 000...1111, which
1829 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001830 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001831 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001832 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001833 if (!UseSrcReg)
1834 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001835 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001836 tmpInst.addOperand(MCOperand::createReg(DstReg));
1837 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1838 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001839 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001840 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001841 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001842 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001843 if (!UseSrcReg)
1844 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001845 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001846 tmpInst.addOperand(MCOperand::createReg(DstReg));
1847 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1848 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001849 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001850 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001851 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001852
Toma Tabacuae47f932015-04-10 13:28:16 +00001853 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001854 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001855 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001856 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1857 uint16_t Bits15To0 = ImmValue & 0xffff;
1858
Toma Tabacua3d056f2015-05-15 09:42:11 +00001859 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1860 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1861 // upper 32 bits.
1862 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001863 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Toma Tabacua3d056f2015-05-15 09:42:11 +00001864 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1865 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1866 tmpInst.setLoc(IDLoc);
1867 Instructions.push_back(tmpInst);
1868 // Move the value to the upper 16 bits by doing a 16-bit left shift.
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001869 createLShiftOri<16>(0, TmpReg, IDLoc, Instructions);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001870 } else {
1871 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001872 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Toma Tabacua3d056f2015-05-15 09:42:11 +00001873 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1874 Instructions.push_back(tmpInst);
1875 }
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001876 createLShiftOri<0>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001877
1878 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001879 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001880
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001881 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001882 if (Is32BitImm) {
1883 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001884 return true;
1885 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001886 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001887
1888 // <------- lo32 ------>
1889 // <------- hi32 ------>
1890 // <- hi16 -> <- lo16 ->
1891 // _________________________________
1892 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001893 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001894 // |__________|__________|__________|
1895 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001896 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001897 // li d,j => lui d,hi16(j)
1898 // ori d,d,hi16(lo32(j))
1899 // dsll d,d,16
1900 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001901 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1902 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1903 uint16_t Bits15To0 = ImmValue & 0xffff;
1904
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001905 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001906 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00001907 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001908 Instructions.push_back(tmpInst);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001909 createLShiftOri<0>(Bits31To16, TmpReg, IDLoc, Instructions);
1910 createLShiftOri<16>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001911
1912 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001913 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001914
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001915 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001916 if (Is32BitImm) {
1917 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001918 return true;
1919 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001920 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001921
1922 // <------- hi32 ------> <------- lo32 ------>
1923 // <- hi16 -> <- lo16 ->
1924 // ___________________________________________
1925 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001926 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001927 // |__________|__________|__________|__________|
1928 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001929 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001930 // li d,j => lui d,hi16(j)
1931 // ori d,d,lo16(hi32(j))
1932 // dsll d,d,16
1933 // ori d,d,hi16(lo32(j))
1934 // dsll d,d,16
1935 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001936 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1937 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1938 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1939 uint16_t Bits15To0 = ImmValue & 0xffff;
1940
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001941 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001942 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00001943 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001944 Instructions.push_back(tmpInst);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001945 createLShiftOri<0>(Bits47To32, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001946
1947 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1948 // two left shifts of 16 bits.
1949 if (Bits31To16 == 0) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001950 createLShiftOri<32>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001951 } else {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001952 createLShiftOri<16>(Bits31To16, TmpReg, IDLoc, Instructions);
1953 createLShiftOri<16>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001954 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001955
1956 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001957 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001958 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001959 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001960}
Jack Carter92995f12012-10-06 00:53:28 +00001961
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001962bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1963 SmallVectorImpl<MCInst> &Instructions) {
1964 const MCOperand &ImmOp = Inst.getOperand(1);
1965 assert(ImmOp.isImm() && "expected immediate operand kind");
1966 const MCOperand &DstRegOp = Inst.getOperand(0);
1967 assert(DstRegOp.isReg() && "expected register operand kind");
1968
1969 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1970 Is32BitImm, IDLoc, Instructions))
1971 return true;
1972
1973 return false;
1974}
1975
Matheus Almeida3813d572014-06-19 14:39:14 +00001976bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001977MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001978 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001979 const MCOperand &DstRegOp = Inst.getOperand(0);
1980 assert(DstRegOp.isReg() && "expected register operand kind");
1981
Toma Tabacuf712ede2015-06-17 14:31:51 +00001982 const MCOperand &SrcRegOp = Inst.getOperand(1);
1983 assert(SrcRegOp.isReg() && "expected register operand kind");
1984
Jack Carter543fdf82012-10-09 23:29:45 +00001985 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001986 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1987 "expected immediate operand kind");
1988 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00001989 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
1990 SrcRegOp.getReg(), Is32BitImm, IDLoc,
1991 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00001992 return true;
1993
Toma Tabacu0d64b202014-08-14 10:29:17 +00001994 return false;
1995 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001996
1997 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
1998 Is32BitImm, IDLoc, Instructions))
1999 return true;
2000
Matheus Almeida3813d572014-06-19 14:39:14 +00002001 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00002002}
2003
Matheus Almeida3813d572014-06-19 14:39:14 +00002004bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002005MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002006 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00002007 const MCOperand &DstRegOp = Inst.getOperand(0);
2008 assert(DstRegOp.isReg() && "expected register operand kind");
2009
Jack Carter543fdf82012-10-09 23:29:45 +00002010 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002011 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
2012 "expected immediate operand kind");
2013 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00002014 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
2015 Mips::NoRegister, Is32BitImm, IDLoc,
2016 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00002017 return true;
2018
Toma Tabacu0d64b202014-08-14 10:29:17 +00002019 return false;
2020 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002021
2022 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
2023 Is32BitImm, IDLoc, Instructions))
2024 return true;
2025
Matheus Almeida3813d572014-06-19 14:39:14 +00002026 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00002027}
2028
Toma Tabacuf712ede2015-06-17 14:31:51 +00002029bool MipsAsmParser::loadAndAddSymbolAddress(
2030 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2031 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002032 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002033
Toma Tabacuec1de822015-05-14 10:53:40 +00002034 if (Is32BitSym && isABI_N64())
2035 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
2036
Toma Tabacu0d64b202014-08-14 10:29:17 +00002037 MCInst tmpInst;
Toma Tabacu674825c2015-06-16 12:16:24 +00002038 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002039 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2040 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2041 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2042 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2043
Toma Tabacufb9d1252015-06-22 12:08:39 +00002044 bool UseSrcReg = SrcReg != Mips::NoRegister;
2045
2046 unsigned TmpReg = DstReg;
2047 if (UseSrcReg && (DstReg == SrcReg)) {
2048 // At this point we need AT to perform the expansions and we exit if it is
2049 // not available.
2050 unsigned ATReg = getATReg(IDLoc);
2051 if (!ATReg)
2052 return true;
2053 TmpReg = ATReg;
2054 }
2055
Toma Tabacuec1de822015-05-14 10:53:40 +00002056 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00002057 // If it's a 64-bit architecture, expand to:
2058 // la d,sym => lui d,highest(sym)
2059 // ori d,d,higher(sym)
2060 // dsll d,d,16
2061 // ori d,d,hi16(sym)
2062 // dsll d,d,16
2063 // ori d,d,lo16(sym)
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002064 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2065 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2066 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2067 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
Toma Tabacu0d64b202014-08-14 10:29:17 +00002068
2069 tmpInst.setOpcode(Mips::LUi);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002070 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002071 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002072 Instructions.push_back(tmpInst);
2073
Toma Tabacufb9d1252015-06-22 12:08:39 +00002074 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), TmpReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002075 Instructions);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002076 createLShiftOri<16>(MCOperand::createExpr(HiExpr), TmpReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002077 Instructions);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002078 createLShiftOri<16>(MCOperand::createExpr(LoExpr), TmpReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002079 Instructions);
2080 } else {
2081 // Otherwise, expand to:
2082 // la d,sym => lui d,hi16(sym)
2083 // ori d,d,lo16(sym)
2084 tmpInst.setOpcode(Mips::LUi);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002085 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002086 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002087 Instructions.push_back(tmpInst);
2088
Toma Tabacufb9d1252015-06-22 12:08:39 +00002089 createLShiftOri<0>(MCOperand::createExpr(LoExpr), TmpReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002090 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002091 }
Toma Tabacuf712ede2015-06-17 14:31:51 +00002092
Toma Tabacufb9d1252015-06-22 12:08:39 +00002093 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002094 createAddu(DstReg, TmpReg, SrcReg, !Is32BitSym, Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002095
Toma Tabacu674825c2015-06-16 12:16:24 +00002096 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002097}
2098
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002099bool MipsAsmParser::expandUncondBranchMMPseudo(
2100 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002101 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2102 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002103
2104 MCOperand Offset = Inst.getOperand(0);
2105 if (Offset.isExpr()) {
2106 Inst.clear();
2107 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002108 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2109 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2110 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002111 } else {
2112 assert(Offset.isImm() && "expected immediate operand kind");
2113 if (isIntN(11, Offset.getImm())) {
2114 // If offset fits into 11 bits then this instruction becomes microMIPS
2115 // 16-bit unconditional branch instruction.
2116 Inst.setOpcode(Mips::B16_MM);
2117 } else {
2118 if (!isIntN(17, Offset.getImm()))
2119 Error(IDLoc, "branch target out of range");
2120 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2121 Error(IDLoc, "branch to misaligned address");
2122 Inst.clear();
2123 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002124 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2125 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2126 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002127 }
2128 }
2129 Instructions.push_back(Inst);
2130
Toma Tabacu234482a2015-03-16 12:03:39 +00002131 // If .set reorder is active, emit a NOP after the branch instruction.
2132 if (AssemblerOptions.back()->isReorder())
2133 createNop(true, IDLoc, Instructions);
2134
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002135 return false;
2136}
2137
Toma Tabacue1e460d2015-06-11 10:36:10 +00002138bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2139 SmallVectorImpl<MCInst> &Instructions) {
2140 const MCOperand &DstRegOp = Inst.getOperand(0);
2141 assert(DstRegOp.isReg() && "expected register operand kind");
2142
2143 const MCOperand &ImmOp = Inst.getOperand(1);
2144 assert(ImmOp.isImm() && "expected immediate operand kind");
2145
2146 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2147 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2148
2149 unsigned OpCode = 0;
2150 switch(Inst.getOpcode()) {
2151 case Mips::BneImm:
2152 OpCode = Mips::BNE;
2153 break;
2154 case Mips::BeqImm:
2155 OpCode = Mips::BEQ;
2156 break;
2157 default:
2158 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2159 break;
2160 }
2161
2162 int64_t ImmValue = ImmOp.getImm();
2163 if (ImmValue == 0) {
2164 MCInst BranchInst;
2165 BranchInst.setOpcode(OpCode);
2166 BranchInst.addOperand(DstRegOp);
2167 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2168 BranchInst.addOperand(MemOffsetOp);
2169 Instructions.push_back(BranchInst);
2170 } else {
2171 warnIfNoMacro(IDLoc);
2172
2173 unsigned ATReg = getATReg(IDLoc);
2174 if (!ATReg)
2175 return true;
2176
2177 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc,
2178 Instructions))
2179 return true;
2180
2181 MCInst BranchInst;
2182 BranchInst.setOpcode(OpCode);
2183 BranchInst.addOperand(DstRegOp);
2184 BranchInst.addOperand(MCOperand::createReg(ATReg));
2185 BranchInst.addOperand(MemOffsetOp);
2186 Instructions.push_back(BranchInst);
2187 }
2188 return false;
2189}
2190
Jack Carter9e65aa32013-03-22 00:05:30 +00002191void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002192 SmallVectorImpl<MCInst> &Instructions,
2193 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002194 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002196 const MCExpr *ExprOffset;
2197 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002198 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002199 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2200 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002201 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002202 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2203 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002204 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002205 if (isImmOpnd) {
2206 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2207 ImmOffset = Inst.getOperand(2).getImm();
2208 LoOffset = ImmOffset & 0x0000ffff;
2209 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002211 if (LoOffset & 0x8000)
2212 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002213 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002214 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002215 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002216 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002217 // These are some of the types of expansions we perform here:
2218 // 1) lw $8, sym => lui $8, %hi(sym)
2219 // lw $8, %lo(sym)($8)
2220 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2221 // add $8, $8, $9
2222 // lw $8, %lo(offset)($9)
2223 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2224 // add $at, $at, $8
2225 // lw $8, %lo(offset)($at)
2226 // 4) sw $8, sym => lui $at, %hi(sym)
2227 // sw $8, %lo(sym)($at)
2228 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2229 // add $at, $at, $8
2230 // sw $8, %lo(offset)($at)
2231 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2232 // ldc1 $f0, %lo(sym)($at)
2233 //
2234 // For load instructions we can use the destination register as a temporary
2235 // if base and dst are different (examples 1 and 2) and if the base register
2236 // is general purpose otherwise we must use $at (example 6) and error if it's
2237 // not available. For stores we must use $at (examples 4 and 5) because we
2238 // must not clobber the source register setting up the offset.
2239 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2240 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2241 unsigned RegClassIDOp0 =
2242 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2243 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2244 (RegClassIDOp0 == Mips::GPR64RegClassID);
2245 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002246 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002247 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002248 // At this point we need AT to perform the expansions and we exit if it is
2249 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002250 TmpRegNum = getATReg(IDLoc);
2251 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002252 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002253 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002254
Jack Carter9e65aa32013-03-22 00:05:30 +00002255 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002256 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002257 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002258 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002259 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002260 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2261 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002262 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002263 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002264 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002265 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002266 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002267 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002268 if (BaseRegNum != Mips::ZERO) {
2269 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002270 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2271 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2272 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002273 Instructions.push_back(TempInst);
2274 TempInst.clear();
2275 }
Alp Tokercb402912014-01-24 17:20:08 +00002276 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002278 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002279 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2280 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002281 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002282 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002283 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002284 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2285 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002286 }
2287 Instructions.push_back(TempInst);
2288 TempInst.clear();
2289}
2290
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002291bool
2292MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2293 SmallVectorImpl<MCInst> &Instructions) {
2294 unsigned OpNum = Inst.getNumOperands();
2295 unsigned Opcode = Inst.getOpcode();
2296 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2297
2298 assert (Inst.getOperand(OpNum - 1).isImm() &&
2299 Inst.getOperand(OpNum - 2).isReg() &&
2300 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2301
2302 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2303 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2304 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2305 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2306 // It can be implemented as SWM16 or LWM16 instruction.
2307 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2308
2309 Inst.setOpcode(NewOpcode);
2310 Instructions.push_back(Inst);
2311 return false;
2312}
2313
Toma Tabacu1a108322015-06-17 13:20:24 +00002314bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2315 SmallVectorImpl<MCInst> &Instructions) {
2316 unsigned PseudoOpcode = Inst.getOpcode();
2317 unsigned SrcReg = Inst.getOperand(0).getReg();
2318 unsigned TrgReg = Inst.getOperand(1).getReg();
2319 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2320
2321 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2322 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2323
2324 switch (PseudoOpcode) {
2325 case Mips::BLT:
2326 case Mips::BLTU:
2327 AcceptsEquality = false;
2328 ReverseOrderSLT = false;
2329 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2330 ZeroSrcOpcode = Mips::BGTZ;
2331 ZeroTrgOpcode = Mips::BLTZ;
2332 break;
2333 case Mips::BLE:
2334 case Mips::BLEU:
2335 AcceptsEquality = true;
2336 ReverseOrderSLT = true;
2337 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2338 ZeroSrcOpcode = Mips::BGEZ;
2339 ZeroTrgOpcode = Mips::BLEZ;
2340 break;
2341 case Mips::BGE:
2342 case Mips::BGEU:
2343 AcceptsEquality = true;
2344 ReverseOrderSLT = false;
2345 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2346 ZeroSrcOpcode = Mips::BLEZ;
2347 ZeroTrgOpcode = Mips::BGEZ;
2348 break;
2349 case Mips::BGT:
2350 case Mips::BGTU:
2351 AcceptsEquality = false;
2352 ReverseOrderSLT = true;
2353 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2354 ZeroSrcOpcode = Mips::BLTZ;
2355 ZeroTrgOpcode = Mips::BGTZ;
2356 break;
2357 default:
2358 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2359 }
2360
2361 MCInst BranchInst;
2362 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2363 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2364 if (IsSrcRegZero && IsTrgRegZero) {
2365 // FIXME: All of these Opcode-specific if's are needed for compatibility
2366 // with GAS' behaviour. However, they may not generate the most efficient
2367 // code in some circumstances.
2368 if (PseudoOpcode == Mips::BLT) {
2369 BranchInst.setOpcode(Mips::BLTZ);
2370 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2371 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2372 Instructions.push_back(BranchInst);
2373 return false;
2374 }
2375 if (PseudoOpcode == Mips::BLE) {
2376 BranchInst.setOpcode(Mips::BLEZ);
2377 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2378 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2379 Instructions.push_back(BranchInst);
2380 Warning(IDLoc, "branch is always taken");
2381 return false;
2382 }
2383 if (PseudoOpcode == Mips::BGE) {
2384 BranchInst.setOpcode(Mips::BGEZ);
2385 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2386 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2387 Instructions.push_back(BranchInst);
2388 Warning(IDLoc, "branch is always taken");
2389 return false;
2390 }
2391 if (PseudoOpcode == Mips::BGT) {
2392 BranchInst.setOpcode(Mips::BGTZ);
2393 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2394 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2395 Instructions.push_back(BranchInst);
2396 return false;
2397 }
2398 if (PseudoOpcode == Mips::BGTU) {
2399 BranchInst.setOpcode(Mips::BNE);
2400 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2401 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2402 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2403 Instructions.push_back(BranchInst);
2404 return false;
2405 }
2406 if (AcceptsEquality) {
2407 // If both registers are $0 and the pseudo-branch accepts equality, it
2408 // will always be taken, so we emit an unconditional branch.
2409 BranchInst.setOpcode(Mips::BEQ);
2410 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2411 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2412 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2413 Instructions.push_back(BranchInst);
2414 Warning(IDLoc, "branch is always taken");
2415 return false;
2416 }
2417 // If both registers are $0 and the pseudo-branch does not accept
2418 // equality, it will never be taken, so we don't have to emit anything.
2419 return false;
2420 }
2421 if (IsSrcRegZero || IsTrgRegZero) {
2422 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2423 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2424 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2425 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2426 // the pseudo-branch will never be taken, so we don't emit anything.
2427 // This only applies to unsigned pseudo-branches.
2428 return false;
2429 }
2430 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2431 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2432 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2433 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2434 // the pseudo-branch will always be taken, so we emit an unconditional
2435 // branch.
2436 // This only applies to unsigned pseudo-branches.
2437 BranchInst.setOpcode(Mips::BEQ);
2438 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2439 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2440 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2441 Instructions.push_back(BranchInst);
2442 Warning(IDLoc, "branch is always taken");
2443 return false;
2444 }
2445 if (IsUnsigned) {
2446 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2447 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2448 // the pseudo-branch will be taken only when the non-zero register is
2449 // different from 0, so we emit a BNEZ.
2450 //
2451 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2452 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2453 // the pseudo-branch will be taken only when the non-zero register is
2454 // equal to 0, so we emit a BEQZ.
2455 //
2456 // Because only BLEU and BGEU branch on equality, we can use the
2457 // AcceptsEquality variable to decide when to emit the BEQZ.
2458 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2459 BranchInst.addOperand(
2460 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2461 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2462 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2463 Instructions.push_back(BranchInst);
2464 return false;
2465 }
2466 // If we have a signed pseudo-branch and one of the registers is $0,
2467 // we can use an appropriate compare-to-zero branch. We select which one
2468 // to use in the switch statement above.
2469 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2470 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2471 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2472 Instructions.push_back(BranchInst);
2473 return false;
2474 }
2475
2476 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2477 // expansions. If it is not available, we return.
2478 unsigned ATRegNum = getATReg(IDLoc);
2479 if (!ATRegNum)
2480 return true;
2481
2482 warnIfNoMacro(IDLoc);
2483
2484 // SLT fits well with 2 of our 4 pseudo-branches:
2485 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2486 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2487 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2488 // This is accomplished by using a BNEZ with the result of the SLT.
2489 //
2490 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2491 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2492 // Because only BGE and BLE branch on equality, we can use the
2493 // AcceptsEquality variable to decide when to emit the BEQZ.
2494 // Note that the order of the SLT arguments doesn't change between
2495 // opposites.
2496 //
2497 // The same applies to the unsigned variants, except that SLTu is used
2498 // instead of SLT.
2499 MCInst SetInst;
2500 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2501 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2502 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2503 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2504 Instructions.push_back(SetInst);
2505
2506 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2507 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2508 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2509 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2510 Instructions.push_back(BranchInst);
2511 return false;
2512}
2513
Toma Tabacud88d79c2015-06-23 14:39:42 +00002514bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2515 SmallVectorImpl<MCInst> &Instructions) {
2516 if (hasMips32r6() || hasMips64r6()) {
2517 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2518 return false;
2519 }
2520
2521 warnIfNoMacro(IDLoc);
2522
2523 const MCOperand &DstRegOp = Inst.getOperand(0);
2524 assert(DstRegOp.isReg() && "expected register operand kind");
2525
2526 const MCOperand &SrcRegOp = Inst.getOperand(1);
2527 assert(SrcRegOp.isReg() && "expected register operand kind");
2528
2529 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2530 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2531
2532 unsigned DstReg = DstRegOp.getReg();
2533 unsigned SrcReg = SrcRegOp.getReg();
2534 int64_t OffsetValue = OffsetImmOp.getImm();
2535
2536 // NOTE: We always need AT for ULHU, as it is always used as the source
2537 // register for one of the LBu's.
2538 unsigned ATReg = getATReg(IDLoc);
2539 if (!ATReg)
2540 return true;
2541
2542 // When the value of offset+1 does not fit in 16 bits, we have to load the
2543 // offset in AT, (D)ADDu the original source register (if there was one), and
2544 // then use AT as the source register for the 2 generated LBu's.
2545 bool LoadedOffsetInAT = false;
2546 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2547 LoadedOffsetInAT = true;
2548
2549 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
2550 IDLoc, Instructions))
2551 return true;
2552
2553 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2554 // because it will make our output more similar to GAS'. For example,
2555 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2556 // instead of just an "ori $1, $9, 32768".
2557 // NOTE: If there is no source register specified in the ULHU, the parser
2558 // will interpret it as $0.
2559 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2560 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2561 }
2562
2563 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2564 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2565 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2566
2567 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2568 if (isLittle()) {
2569 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2570 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2571 } else {
2572 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2573 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2574 }
2575
2576 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2577
2578 MCInst TmpInst;
2579 TmpInst.setOpcode(Mips::LBu);
2580 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2581 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2582 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2583 Instructions.push_back(TmpInst);
2584
2585 TmpInst.clear();
2586 TmpInst.setOpcode(Mips::LBu);
2587 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2588 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2589 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2590 Instructions.push_back(TmpInst);
2591
2592 TmpInst.clear();
2593 TmpInst.setOpcode(Mips::SLL);
2594 TmpInst.addOperand(MCOperand::createReg(SllReg));
2595 TmpInst.addOperand(MCOperand::createReg(SllReg));
2596 TmpInst.addOperand(MCOperand::createImm(8));
2597 Instructions.push_back(TmpInst);
2598
2599 TmpInst.clear();
2600 TmpInst.setOpcode(Mips::OR);
2601 TmpInst.addOperand(MCOperand::createReg(DstReg));
2602 TmpInst.addOperand(MCOperand::createReg(DstReg));
2603 TmpInst.addOperand(MCOperand::createReg(ATReg));
2604 Instructions.push_back(TmpInst);
2605
2606 return false;
2607}
2608
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002609bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
2610 SmallVectorImpl<MCInst> &Instructions) {
2611 if (hasMips32r6() || hasMips64r6()) {
2612 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2613 return false;
2614 }
2615
2616 const MCOperand &DstRegOp = Inst.getOperand(0);
2617 assert(DstRegOp.isReg() && "expected register operand kind");
2618
2619 const MCOperand &SrcRegOp = Inst.getOperand(1);
2620 assert(SrcRegOp.isReg() && "expected register operand kind");
2621
2622 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2623 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2624
2625 unsigned SrcReg = SrcRegOp.getReg();
2626 int64_t OffsetValue = OffsetImmOp.getImm();
2627 unsigned ATReg = 0;
2628
2629 // When the value of offset+3 does not fit in 16 bits, we have to load the
2630 // offset in AT, (D)ADDu the original source register (if there was one), and
2631 // then use AT as the source register for the generated LWL and LWR.
2632 bool LoadedOffsetInAT = false;
2633 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
2634 ATReg = getATReg(IDLoc);
2635 if (!ATReg)
2636 return true;
2637 LoadedOffsetInAT = true;
2638
2639 warnIfNoMacro(IDLoc);
2640
2641 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
2642 IDLoc, Instructions))
2643 return true;
2644
2645 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2646 // because it will make our output more similar to GAS'. For example,
2647 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2648 // instead of just an "ori $1, $9, 32768".
2649 // NOTE: If there is no source register specified in the ULW, the parser
2650 // will interpret it as $0.
2651 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2652 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2653 }
2654
2655 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2656 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
2657 if (isLittle()) {
2658 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2659 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2660 } else {
2661 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2662 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2663 }
2664
2665 MCInst LeftLoadInst;
2666 LeftLoadInst.setOpcode(Mips::LWL);
2667 LeftLoadInst.addOperand(DstRegOp);
2668 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2669 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
2670 Instructions.push_back(LeftLoadInst);
2671
2672 MCInst RightLoadInst;
2673 RightLoadInst.setOpcode(Mips::LWR);
2674 RightLoadInst.addOperand(DstRegOp);
2675 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2676 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
2677 Instructions.push_back(RightLoadInst);
2678
2679 return false;
2680}
2681
Toma Tabacu234482a2015-03-16 12:03:39 +00002682void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2683 SmallVectorImpl<MCInst> &Instructions) {
2684 MCInst NopInst;
2685 if (hasShortDelaySlot) {
2686 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002687 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2688 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002689 } else {
2690 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002691 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2692 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2693 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002694 }
2695 Instructions.push_back(NopInst);
2696}
2697
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002698void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002699 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002700 SmallVectorImpl<MCInst> &Instructions) {
2701 MCInst AdduInst;
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002702 AdduInst.setOpcode(Is64Bit ? Mips::DADDu : Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002703 AdduInst.addOperand(MCOperand::createReg(DstReg));
2704 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2705 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002706 Instructions.push_back(AdduInst);
2707}
2708
Matheus Almeida595fcab2014-06-11 15:05:56 +00002709unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2710 // As described by the Mips32r2 spec, the registers Rd and Rs for
2711 // jalr.hb must be different.
2712 unsigned Opcode = Inst.getOpcode();
2713
2714 if (Opcode == Mips::JALR_HB &&
2715 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2716 return Match_RequiresDifferentSrcAndDst;
2717
2718 return Match_Success;
2719}
2720
David Blaikie960ea3f2014-06-08 16:18:35 +00002721bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2722 OperandVector &Operands,
2723 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002724 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002725 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002726
Jack Carterb4dbc172012-09-05 23:34:03 +00002727 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002728 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002729 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00002730 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002731
2732 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002733 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002734 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002735 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002736 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002737 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002738 return false;
2739 }
2740 case Match_MissingFeature:
2741 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2742 return true;
2743 case Match_InvalidOperand: {
2744 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002745 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002746 if (ErrorInfo >= Operands.size())
2747 return Error(IDLoc, "too few operands for instruction");
2748
David Blaikie960ea3f2014-06-08 16:18:35 +00002749 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002750 if (ErrorLoc == SMLoc())
2751 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002752 }
2753
2754 return Error(ErrorLoc, "invalid operand for instruction");
2755 }
2756 case Match_MnemonicFail:
2757 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002758 case Match_RequiresDifferentSrcAndDst:
2759 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002760 }
Craig Topper589ceee2015-01-03 08:16:34 +00002761
2762 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002763}
2764
Toma Tabacud9d344b2015-04-27 14:05:04 +00002765void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2766 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2767 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2768 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002769}
2770
Toma Tabacu81496c12015-05-20 08:54:45 +00002771void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2772 if (!AssemblerOptions.back()->isMacro())
2773 Warning(Loc, "macro instruction expanded into multiple instructions");
2774}
2775
Daniel Sandersef638fe2014-10-03 15:37:37 +00002776void
2777MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2778 SMRange Range, bool ShowColors) {
2779 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002780 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002781 ShowColors);
2782}
2783
Jack Carter1ac53222013-02-20 23:11:17 +00002784int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002785 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002786
Vladimir Medic4c299852013-11-06 11:27:05 +00002787 CC = StringSwitch<unsigned>(Name)
2788 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002789 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002790 .Case("a0", 4)
2791 .Case("a1", 5)
2792 .Case("a2", 6)
2793 .Case("a3", 7)
2794 .Case("v0", 2)
2795 .Case("v1", 3)
2796 .Case("s0", 16)
2797 .Case("s1", 17)
2798 .Case("s2", 18)
2799 .Case("s3", 19)
2800 .Case("s4", 20)
2801 .Case("s5", 21)
2802 .Case("s6", 22)
2803 .Case("s7", 23)
2804 .Case("k0", 26)
2805 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002806 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002807 .Case("sp", 29)
2808 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002809 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002810 .Case("ra", 31)
2811 .Case("t0", 8)
2812 .Case("t1", 9)
2813 .Case("t2", 10)
2814 .Case("t3", 11)
2815 .Case("t4", 12)
2816 .Case("t5", 13)
2817 .Case("t6", 14)
2818 .Case("t7", 15)
2819 .Case("t8", 24)
2820 .Case("t9", 25)
2821 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002822
Toma Tabacufda445c2014-09-15 15:33:01 +00002823 if (!(isABI_N32() || isABI_N64()))
2824 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002825
Daniel Sandersef638fe2014-10-03 15:37:37 +00002826 if (12 <= CC && CC <= 15) {
2827 // Name is one of t4-t7
2828 AsmToken RegTok = getLexer().peekTok();
2829 SMRange RegRange = RegTok.getLocRange();
2830
2831 StringRef FixedName = StringSwitch<StringRef>(Name)
2832 .Case("t4", "t0")
2833 .Case("t5", "t1")
2834 .Case("t6", "t2")
2835 .Case("t7", "t3")
2836 .Default("");
2837 assert(FixedName != "" && "Register name is not one of t4-t7.");
2838
2839 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2840 "Did you mean $" + FixedName + "?", RegRange);
2841 }
2842
Toma Tabacufda445c2014-09-15 15:33:01 +00002843 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2844 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2845 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2846 if (8 <= CC && CC <= 11)
2847 CC += 4;
2848
2849 if (CC == -1)
2850 CC = StringSwitch<unsigned>(Name)
2851 .Case("a4", 8)
2852 .Case("a5", 9)
2853 .Case("a6", 10)
2854 .Case("a7", 11)
2855 .Case("kt0", 26)
2856 .Case("kt1", 27)
2857 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002858
2859 return CC;
2860}
Jack Carterd0bd6422013-04-18 00:41:53 +00002861
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002862int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2863 int CC;
2864
2865 CC = StringSwitch<unsigned>(Name)
2866 .Case("hwr_cpunum", 0)
2867 .Case("hwr_synci_step", 1)
2868 .Case("hwr_cc", 2)
2869 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002870 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002871 .Default(-1);
2872
2873 return CC;
2874}
2875
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002876int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002877
Jack Cartera63b16a2012-09-07 00:23:42 +00002878 if (Name[0] == 'f') {
2879 StringRef NumString = Name.substr(1);
2880 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002881 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002882 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002883 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002884 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002885 return IntVal;
2886 }
2887 return -1;
2888}
Jack Cartera63b16a2012-09-07 00:23:42 +00002889
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002890int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2891
2892 if (Name.startswith("fcc")) {
2893 StringRef NumString = Name.substr(3);
2894 unsigned IntVal;
2895 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002896 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002897 if (IntVal > 7) // There are only 8 fcc registers.
2898 return -1;
2899 return IntVal;
2900 }
2901 return -1;
2902}
2903
2904int MipsAsmParser::matchACRegisterName(StringRef Name) {
2905
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002906 if (Name.startswith("ac")) {
2907 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002908 unsigned IntVal;
2909 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002910 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002911 if (IntVal > 3) // There are only 3 acc registers.
2912 return -1;
2913 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002914 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002915 return -1;
2916}
Jack Carterd0bd6422013-04-18 00:41:53 +00002917
Jack Carter5dc8ac92013-09-25 23:50:44 +00002918int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2919 unsigned IntVal;
2920
2921 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2922 return -1;
2923
2924 if (IntVal > 31)
2925 return -1;
2926
2927 return IntVal;
2928}
2929
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002930int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2931 int CC;
2932
2933 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002934 .Case("msair", 0)
2935 .Case("msacsr", 1)
2936 .Case("msaaccess", 2)
2937 .Case("msasave", 3)
2938 .Case("msamodify", 4)
2939 .Case("msarequest", 5)
2940 .Case("msamap", 6)
2941 .Case("msaunmap", 7)
2942 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002943
2944 return CC;
2945}
2946
Toma Tabacu89a712b2015-04-15 10:48:56 +00002947unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002948 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002949 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002950 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002951 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002952 return 0;
2953 }
2954 unsigned AT = getReg(
2955 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002956 return AT;
2957}
Jack Carter0b744b32012-10-04 02:29:46 +00002958
Jack Carterd0bd6422013-04-18 00:41:53 +00002959unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002960 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002961}
2962
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002963unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002964 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002965 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002966}
2967
Jack Carter873c7242013-01-12 01:03:14 +00002968int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002969 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002970 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002971 return -1;
2972
Jack Carter873c7242013-01-12 01:03:14 +00002973 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002974}
2975
Toma Tabacu13964452014-09-04 13:23:44 +00002976bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002977 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002978 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002979
Jack Carter30a59822012-10-04 04:03:53 +00002980 // Check if the current operand has a custom associated parser, if so, try to
2981 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002982 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2983 if (ResTy == MatchOperand_Success)
2984 return false;
2985 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2986 // there was a match, but an error occurred, in which case, just return that
2987 // the operand parsing failed.
2988 if (ResTy == MatchOperand_ParseFail)
2989 return true;
2990
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002991 DEBUG(dbgs() << ".. Generic Parser\n");
2992
Jack Carterb4dbc172012-09-05 23:34:03 +00002993 switch (getLexer().getKind()) {
2994 default:
2995 Error(Parser.getTok().getLoc(), "unexpected token in operand");
2996 return true;
2997 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002998 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00002999 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003000
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003001 // Almost all registers have been parsed by custom parsers. There is only
3002 // one exception to this. $zero (and it's alias $0) will reach this point
3003 // for div, divu, and similar instructions because it is not an operand
3004 // to the instruction definition but an explicit register. Special case
3005 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003006 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003007 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003008
Jack Carterd0bd6422013-04-18 00:41:53 +00003009 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003010 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003011 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003012 return true;
3013
Jack Carter873c7242013-01-12 01:03:14 +00003014 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003015 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003016 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003017 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003018 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003019
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003020 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003021 return false;
3022 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003023 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003024 case AsmToken::LParen:
3025 case AsmToken::Minus:
3026 case AsmToken::Plus:
3027 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003028 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003029 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003030 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003031 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003032 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003033 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003034 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003035 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003036 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003037 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003038 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003039 return true;
3040
Jack Carter873c7242013-01-12 01:03:14 +00003041 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3042
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003043 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003044 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003045 } // case AsmToken::Percent
3046 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003047 return true;
3048}
3049
Vladimir Medic4c299852013-11-06 11:27:05 +00003050const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003051 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003052 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003053 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003054 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003055 // It's a constant, evaluate reloc value.
3056 int16_t Val;
3057 switch (getVariantKind(RelocStr)) {
3058 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3059 // Get the 1st 16-bits.
3060 Val = MCE->getValue() & 0xffff;
3061 break;
3062 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3063 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3064 // 16 bits being negative.
3065 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3066 break;
3067 case MCSymbolRefExpr::VK_Mips_HIGHER:
3068 // Get the 3rd 16-bits.
3069 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3070 break;
3071 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3072 // Get the 4th 16-bits.
3073 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3074 break;
3075 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003076 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003077 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003078 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003079 }
3080
Jack Carterb5cf5902013-04-17 00:18:04 +00003081 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003082 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003083 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003084 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003085 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003086 return Res;
3087 }
3088
3089 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003090 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3091
Sasa Stankovic06c47802014-04-03 10:37:45 +00003092 // Try to create target expression.
3093 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003094 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003095
Jack Carterd0bd6422013-04-18 00:41:53 +00003096 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3097 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003098 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003099 return Res;
3100 }
3101
3102 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003103 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003104 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003105 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003106 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003107 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003108 return Expr;
3109}
3110
3111bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3112
3113 switch (Expr->getKind()) {
3114 case MCExpr::Constant:
3115 return true;
3116 case MCExpr::SymbolRef:
3117 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3118 case MCExpr::Binary:
3119 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3120 if (!isEvaluated(BE->getLHS()))
3121 return false;
3122 return isEvaluated(BE->getRHS());
3123 }
3124 case MCExpr::Unary:
3125 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003126 case MCExpr::Target:
3127 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003128 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003129 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003130}
Jack Carterd0bd6422013-04-18 00:41:53 +00003131
Jack Carterb5cf5902013-04-17 00:18:04 +00003132bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003133 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003134 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003135 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003136 if (Tok.isNot(AsmToken::Identifier))
3137 return true;
3138
Yaron Keren075759a2015-03-30 15:42:36 +00003139 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003140
Jack Carterd0bd6422013-04-18 00:41:53 +00003141 Parser.Lex(); // Eat the identifier.
3142 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003143 const MCExpr *IdVal;
3144 SMLoc EndLoc;
3145
3146 if (getLexer().getKind() == AsmToken::LParen) {
3147 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003148 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003149 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003150 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003151 const AsmToken &nextTok = Parser.getTok();
3152 if (nextTok.isNot(AsmToken::Identifier))
3153 return true;
3154 Str += "(%";
3155 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003156 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003157 if (getLexer().getKind() != AsmToken::LParen)
3158 return true;
3159 } else
3160 break;
3161 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003162 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003163 return true;
3164
3165 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003166 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003167
3168 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003169 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003170
Jack Carterd0bd6422013-04-18 00:41:53 +00003171 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003172 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003173}
3174
Jack Carterb4dbc172012-09-05 23:34:03 +00003175bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3176 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003177 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003178 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003179 if (ResTy == MatchOperand_Success) {
3180 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003181 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003182 StartLoc = Operand.getStartLoc();
3183 EndLoc = Operand.getEndLoc();
3184
3185 // AFAIK, we only support numeric registers and named GPR's in CFI
3186 // directives.
3187 // Don't worry about eating tokens before failing. Using an unrecognised
3188 // register is a parse error.
3189 if (Operand.isGPRAsmReg()) {
3190 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003191 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003192 }
3193
3194 return (RegNo == (unsigned)-1);
3195 }
3196
3197 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003198 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003199}
3200
Jack Carterb5cf5902013-04-17 00:18:04 +00003201bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003202 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003203 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003204 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003205 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003206
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003207 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003208 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003209 ++NumOfLParen;
3210 }
Jack Carter873c7242013-01-12 01:03:14 +00003211
Jack Carterd0bd6422013-04-18 00:41:53 +00003212 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003213 default:
3214 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003215 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003216 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003217 case AsmToken::Integer:
3218 case AsmToken::Minus:
3219 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003220 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003221 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003222 else
3223 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003224 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003225 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003226 break;
Jack Carter873c7242013-01-12 01:03:14 +00003227 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003228 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003229 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003230 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003231}
3232
David Blaikie960ea3f2014-06-08 16:18:35 +00003233MipsAsmParser::OperandMatchResultTy
3234MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003235 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003236 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003237 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003238 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003239 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003240 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003241 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003242 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003243
Jack Carterb5cf5902013-04-17 00:18:04 +00003244 if (getLexer().getKind() == AsmToken::LParen) {
3245 Parser.Lex();
3246 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003247 }
3248
Jack Carterb5cf5902013-04-17 00:18:04 +00003249 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003250 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003251 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003252
Jack Carterd0bd6422013-04-18 00:41:53 +00003253 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003254 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003255 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
3256 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003257 SMLoc E =
3258 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003259 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003260 return MatchOperand_Success;
3261 }
3262 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003263 SMLoc E =
3264 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003265
Jack Carterd0bd6422013-04-18 00:41:53 +00003266 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003267 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003268 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003269 S, E, *this);
3270 Operands.push_back(
3271 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003272 return MatchOperand_Success;
3273 }
3274 Error(Parser.getTok().getLoc(), "'(' expected");
3275 return MatchOperand_ParseFail;
3276 }
3277
Jack Carterd0bd6422013-04-18 00:41:53 +00003278 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003279 }
3280
Toma Tabacu13964452014-09-04 13:23:44 +00003281 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003282 if (Res != MatchOperand_Success)
3283 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003284
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003285 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003286 Error(Parser.getTok().getLoc(), "')' expected");
3287 return MatchOperand_ParseFail;
3288 }
3289
Jack Carter873c7242013-01-12 01:03:14 +00003290 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3291
Jack Carterd0bd6422013-04-18 00:41:53 +00003292 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003293
Craig Topper062a2ba2014-04-25 05:30:21 +00003294 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003295 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003296
Jack Carterd0bd6422013-04-18 00:41:53 +00003297 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003298 std::unique_ptr<MipsOperand> op(
3299 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003300 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003301 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003302 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003304 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3305 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003306 if (IdVal->evaluateAsAbsolute(Imm))
3307 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003308 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003309 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003310 getContext());
3311 }
3312
David Blaikie960ea3f2014-06-08 16:18:35 +00003313 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003314 return MatchOperand_Success;
3315}
3316
David Blaikie960ea3f2014-06-08 16:18:35 +00003317bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003318 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003319 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003320 if (Sym) {
3321 SMLoc S = Parser.getTok().getLoc();
3322 const MCExpr *Expr;
3323 if (Sym->isVariable())
3324 Expr = Sym->getVariableValue();
3325 else
3326 return false;
3327 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003328 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003329 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003330 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003331 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003332 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003333 if (ResTy == MatchOperand_Success) {
3334 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003335 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003336 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003337 llvm_unreachable("Should never ParseFail");
3338 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003339 }
3340 } else if (Expr->getKind() == MCExpr::Constant) {
3341 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003342 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003343 Operands.push_back(
3344 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003345 return true;
3346 }
3347 }
3348 return false;
3349}
Jack Carterd0bd6422013-04-18 00:41:53 +00003350
Jack Carter873c7242013-01-12 01:03:14 +00003351MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003352MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003353 StringRef Identifier,
3354 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003355 int Index = matchCPURegisterName(Identifier);
3356 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003357 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003358 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3359 return MatchOperand_Success;
3360 }
3361
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003362 Index = matchHWRegsRegisterName(Identifier);
3363 if (Index != -1) {
3364 Operands.push_back(MipsOperand::createHWRegsReg(
3365 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3366 return MatchOperand_Success;
3367 }
3368
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003369 Index = matchFPURegisterName(Identifier);
3370 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003371 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003372 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3373 return MatchOperand_Success;
3374 }
3375
3376 Index = matchFCCRegisterName(Identifier);
3377 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003378 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003379 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3380 return MatchOperand_Success;
3381 }
3382
3383 Index = matchACRegisterName(Identifier);
3384 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003385 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003386 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3387 return MatchOperand_Success;
3388 }
3389
3390 Index = matchMSA128RegisterName(Identifier);
3391 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003392 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003393 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3394 return MatchOperand_Success;
3395 }
3396
3397 Index = matchMSA128CtrlRegisterName(Identifier);
3398 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003399 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003400 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3401 return MatchOperand_Success;
3402 }
3403
3404 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003405}
3406
3407MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003408MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003409 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003410 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003411
3412 if (Token.is(AsmToken::Identifier)) {
3413 DEBUG(dbgs() << ".. identifier\n");
3414 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003415 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003416 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003417 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003418 } else if (Token.is(AsmToken::Integer)) {
3419 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003420 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003421 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3422 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003423 return MatchOperand_Success;
3424 }
3425
3426 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3427
3428 return MatchOperand_NoMatch;
3429}
3430
David Blaikie960ea3f2014-06-08 16:18:35 +00003431MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003432MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003433 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003434 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003435
3436 auto Token = Parser.getTok();
3437
3438 SMLoc S = Token.getLoc();
3439
3440 if (Token.isNot(AsmToken::Dollar)) {
3441 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3442 if (Token.is(AsmToken::Identifier)) {
3443 if (searchSymbolAlias(Operands))
3444 return MatchOperand_Success;
3445 }
3446 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3447 return MatchOperand_NoMatch;
3448 }
3449 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003450
Toma Tabacu13964452014-09-04 13:23:44 +00003451 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003452 if (ResTy == MatchOperand_Success) {
3453 Parser.Lex(); // $
3454 Parser.Lex(); // identifier
3455 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003456 return ResTy;
3457}
3458
3459MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003460MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003461 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003462 switch (getLexer().getKind()) {
3463 default:
3464 return MatchOperand_NoMatch;
3465 case AsmToken::LParen:
3466 case AsmToken::Minus:
3467 case AsmToken::Plus:
3468 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003469 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003470 case AsmToken::String:
3471 break;
3472 }
3473
3474 const MCExpr *IdVal;
3475 SMLoc S = Parser.getTok().getLoc();
3476 if (getParser().parseExpression(IdVal))
3477 return MatchOperand_ParseFail;
3478
3479 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3480 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3481 return MatchOperand_Success;
3482}
3483
David Blaikie960ea3f2014-06-08 16:18:35 +00003484MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003485MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003486 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003487 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003488
3489 SMLoc S = getLexer().getLoc();
3490
3491 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003492 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003493 if (ResTy != MatchOperand_NoMatch)
3494 return ResTy;
3495
Daniel Sanders315386c2014-04-01 10:40:14 +00003496 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003497 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003498 if (ResTy != MatchOperand_NoMatch)
3499 return ResTy;
3500
Daniel Sandersffd84362014-04-01 10:41:48 +00003501 const MCExpr *Expr = nullptr;
3502 if (Parser.parseExpression(Expr)) {
3503 // We have no way of knowing if a symbol was consumed so we must ParseFail
3504 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003505 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003506 Operands.push_back(
3507 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003508 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003509}
3510
Vladimir Medic2b953d02013-10-01 09:48:56 +00003511MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003512MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003513 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003514 const MCExpr *IdVal;
3515 // If the first token is '$' we may have register operand.
3516 if (Parser.getTok().is(AsmToken::Dollar))
3517 return MatchOperand_NoMatch;
3518 SMLoc S = Parser.getTok().getLoc();
3519 if (getParser().parseExpression(IdVal))
3520 return MatchOperand_ParseFail;
3521 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003522 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003523 int64_t Val = MCE->getValue();
3524 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3525 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003526 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003527 return MatchOperand_Success;
3528}
3529
Matheus Almeida779c5932013-11-18 12:32:49 +00003530MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003531MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003532 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003533 switch (getLexer().getKind()) {
3534 default:
3535 return MatchOperand_NoMatch;
3536 case AsmToken::LParen:
3537 case AsmToken::Plus:
3538 case AsmToken::Minus:
3539 case AsmToken::Integer:
3540 break;
3541 }
3542
3543 const MCExpr *Expr;
3544 SMLoc S = Parser.getTok().getLoc();
3545
3546 if (getParser().parseExpression(Expr))
3547 return MatchOperand_ParseFail;
3548
3549 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003550 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003551 Error(S, "expected immediate value");
3552 return MatchOperand_ParseFail;
3553 }
3554
3555 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3556 // and because the CPU always adds one to the immediate field, the allowed
3557 // range becomes 1..4. We'll only check the range here and will deal
3558 // with the addition/subtraction when actually decoding/encoding
3559 // the instruction.
3560 if (Val < 1 || Val > 4) {
3561 Error(S, "immediate not in range (1..4)");
3562 return MatchOperand_ParseFail;
3563 }
3564
Jack Carter3b2c96e2014-01-22 23:31:38 +00003565 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003566 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003567 return MatchOperand_Success;
3568}
3569
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003570MipsAsmParser::OperandMatchResultTy
3571MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3572 MCAsmParser &Parser = getParser();
3573 SmallVector<unsigned, 10> Regs;
3574 unsigned RegNo;
3575 unsigned PrevReg = Mips::NoRegister;
3576 bool RegRange = false;
3577 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3578
3579 if (Parser.getTok().isNot(AsmToken::Dollar))
3580 return MatchOperand_ParseFail;
3581
3582 SMLoc S = Parser.getTok().getLoc();
3583 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3584 SMLoc E = getLexer().getLoc();
3585 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3586 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3587 if (RegRange) {
3588 // Remove last register operand because registers from register range
3589 // should be inserted first.
3590 if (RegNo == Mips::RA) {
3591 Regs.push_back(RegNo);
3592 } else {
3593 unsigned TmpReg = PrevReg + 1;
3594 while (TmpReg <= RegNo) {
3595 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3596 Error(E, "invalid register operand");
3597 return MatchOperand_ParseFail;
3598 }
3599
3600 PrevReg = TmpReg;
3601 Regs.push_back(TmpReg++);
3602 }
3603 }
3604
3605 RegRange = false;
3606 } else {
3607 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3608 (RegNo != Mips::RA)) {
3609 Error(E, "$16 or $31 expected");
3610 return MatchOperand_ParseFail;
3611 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3612 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3613 Error(E, "invalid register operand");
3614 return MatchOperand_ParseFail;
3615 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3616 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3617 Error(E, "consecutive register numbers expected");
3618 return MatchOperand_ParseFail;
3619 }
3620
3621 Regs.push_back(RegNo);
3622 }
3623
3624 if (Parser.getTok().is(AsmToken::Minus))
3625 RegRange = true;
3626
3627 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3628 !Parser.getTok().isNot(AsmToken::Comma)) {
3629 Error(E, "',' or '-' expected");
3630 return MatchOperand_ParseFail;
3631 }
3632
3633 Lex(); // Consume comma or minus
3634 if (Parser.getTok().isNot(AsmToken::Dollar))
3635 break;
3636
3637 PrevReg = RegNo;
3638 }
3639
3640 SMLoc E = Parser.getTok().getLoc();
3641 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3642 parseMemOperand(Operands);
3643 return MatchOperand_Success;
3644}
3645
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003646MipsAsmParser::OperandMatchResultTy
3647MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3648 MCAsmParser &Parser = getParser();
3649
3650 SMLoc S = Parser.getTok().getLoc();
3651 if (parseAnyRegister(Operands) != MatchOperand_Success)
3652 return MatchOperand_ParseFail;
3653
3654 SMLoc E = Parser.getTok().getLoc();
3655 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3656 unsigned Reg = Op.getGPR32Reg();
3657 Operands.pop_back();
3658 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3659 return MatchOperand_Success;
3660}
3661
Zoran Jovanovic41688672015-02-10 16:36:20 +00003662MipsAsmParser::OperandMatchResultTy
3663MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3664 MCAsmParser &Parser = getParser();
3665 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3666 SmallVector<unsigned, 10> Regs;
3667
3668 if (Parser.getTok().isNot(AsmToken::Dollar))
3669 return MatchOperand_ParseFail;
3670
3671 SMLoc S = Parser.getTok().getLoc();
3672
3673 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3674 return MatchOperand_ParseFail;
3675
3676 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3677 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3678 Regs.push_back(RegNo);
3679
3680 SMLoc E = Parser.getTok().getLoc();
3681 if (Parser.getTok().isNot(AsmToken::Comma)) {
3682 Error(E, "',' expected");
3683 return MatchOperand_ParseFail;
3684 }
3685
3686 // Remove comma.
3687 Parser.Lex();
3688
3689 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3690 return MatchOperand_ParseFail;
3691
3692 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3693 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3694 Regs.push_back(RegNo);
3695
3696 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3697
3698 return MatchOperand_Success;
3699}
3700
Jack Carterdc1e35d2012-09-06 20:00:02 +00003701MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3702
Vladimir Medic4c299852013-11-06 11:27:05 +00003703 MCSymbolRefExpr::VariantKind VK =
3704 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3705 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3706 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3707 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3708 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3709 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3710 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3711 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3712 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3713 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3714 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3715 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3716 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3717 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3718 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3719 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3720 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3721 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003722 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3723 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3724 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3725 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3726 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3727 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003728 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3729 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003730 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003731
Matheus Almeida2852af82014-04-22 10:15:54 +00003732 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003733
Jack Carterdc1e35d2012-09-06 20:00:02 +00003734 return VK;
3735}
Jack Cartera63b16a2012-09-07 00:23:42 +00003736
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003737/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3738/// either this.
3739/// ::= '(', register, ')'
3740/// handle it before we iterate so we don't get tripped up by the lack of
3741/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003742bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003743 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003744 if (getLexer().is(AsmToken::LParen)) {
3745 Operands.push_back(
3746 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3747 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003748 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003749 SMLoc Loc = getLexer().getLoc();
3750 Parser.eatToEndOfStatement();
3751 return Error(Loc, "unexpected token in argument list");
3752 }
3753 if (Parser.getTok().isNot(AsmToken::RParen)) {
3754 SMLoc Loc = getLexer().getLoc();
3755 Parser.eatToEndOfStatement();
3756 return Error(Loc, "unexpected token, expected ')'");
3757 }
3758 Operands.push_back(
3759 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3760 Parser.Lex();
3761 }
3762 return false;
3763}
3764
3765/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3766/// either one of these.
3767/// ::= '[', register, ']'
3768/// ::= '[', integer, ']'
3769/// handle it before we iterate so we don't get tripped up by the lack of
3770/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003771bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003772 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003773 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003774 if (getLexer().is(AsmToken::LBrac)) {
3775 Operands.push_back(
3776 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3777 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003778 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003779 SMLoc Loc = getLexer().getLoc();
3780 Parser.eatToEndOfStatement();
3781 return Error(Loc, "unexpected token in argument list");
3782 }
3783 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3784 SMLoc Loc = getLexer().getLoc();
3785 Parser.eatToEndOfStatement();
3786 return Error(Loc, "unexpected token, expected ']'");
3787 }
3788 Operands.push_back(
3789 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3790 Parser.Lex();
3791 }
3792 return false;
3793}
3794
David Blaikie960ea3f2014-06-08 16:18:35 +00003795bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3796 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003797 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003798 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003799
3800 // We have reached first instruction, module directive are now forbidden.
3801 getTargetStreamer().forbidModuleDirective();
3802
Vladimir Medic74593e62013-07-17 15:00:42 +00003803 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003804 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003805 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003806 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003807 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003808 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003809 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003810
3811 // Read the remaining operands.
3812 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3813 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003814 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003815 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003816 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003817 return Error(Loc, "unexpected token in argument list");
3818 }
Toma Tabacu13964452014-09-04 13:23:44 +00003819 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003820 return true;
3821 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003822
Jack Carterd0bd6422013-04-18 00:41:53 +00003823 while (getLexer().is(AsmToken::Comma)) {
3824 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003825 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003826 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003827 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003828 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003829 return Error(Loc, "unexpected token in argument list");
3830 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003831 // Parse bracket and parenthesis suffixes before we iterate
3832 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003833 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003834 return true;
3835 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003836 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003837 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003838 }
3839 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003840 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3841 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003842 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003843 return Error(Loc, "unexpected token in argument list");
3844 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003845 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003846 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003847}
3848
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003849bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003850 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003851 SMLoc Loc = getLexer().getLoc();
3852 Parser.eatToEndOfStatement();
3853 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003854}
3855
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003856bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003857 return Error(Loc, ErrorMsg);
3858}
3859
Jack Carter0b744b32012-10-04 02:29:46 +00003860bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003861 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003862 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003863
3864 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003865 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003866
3867 Parser.Lex(); // Eat "noat".
3868
Jack Carterd0bd6422013-04-18 00:41:53 +00003869 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003871 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003872 return false;
3873 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003874
3875 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003876 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003877 return false;
3878}
Jack Carterd0bd6422013-04-18 00:41:53 +00003879
Jack Carter0b744b32012-10-04 02:29:46 +00003880bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003881 // Line can be: ".set at", which sets $at to $1
3882 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003883 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003884 Parser.Lex(); // Eat "at".
3885
Jack Carter0b744b32012-10-04 02:29:46 +00003886 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003887 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003888 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003889
3890 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003891 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003892 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003893 }
3894
3895 if (getLexer().isNot(AsmToken::Equal)) {
3896 reportParseError("unexpected token, expected equals sign");
3897 return false;
3898 }
3899 Parser.Lex(); // Eat "=".
3900
3901 if (getLexer().isNot(AsmToken::Dollar)) {
3902 if (getLexer().is(AsmToken::EndOfStatement)) {
3903 reportParseError("no register specified");
3904 return false;
3905 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003906 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003907 return false;
3908 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003909 }
3910 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003911
Toma Tabacu16a74492015-02-13 10:30:57 +00003912 // Find out what "reg" is.
3913 unsigned AtRegNo;
3914 const AsmToken &Reg = Parser.getTok();
3915 if (Reg.is(AsmToken::Identifier)) {
3916 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3917 } else if (Reg.is(AsmToken::Integer)) {
3918 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003919 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003920 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003921 return false;
3922 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003923
3924 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003925 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003926 reportParseError("invalid register");
3927 return false;
3928 }
3929 Parser.Lex(); // Eat "reg".
3930
3931 // If this is not the end of the statement, report an error.
3932 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3933 reportParseError("unexpected token, expected end of statement");
3934 return false;
3935 }
3936
3937 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3938
3939 Parser.Lex(); // Consume the EndOfStatement.
3940 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003941}
3942
3943bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003944 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003945 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003946 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003947 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003948 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003949 return false;
3950 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003951 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003952 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003953 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003954 return false;
3955}
3956
3957bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003958 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003959 Parser.Lex();
3960 // If this is not the end of the statement, report an error.
3961 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003962 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003963 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003964 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003965 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003966 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003967 Parser.Lex(); // Consume the EndOfStatement.
3968 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003969}
3970
3971bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003972 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003973 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003974 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003975 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003976 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003977 return false;
3978 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003979 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003980 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003981 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003982 return false;
3983}
3984
3985bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003986 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003987 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003988 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003989 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003990 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003991 return false;
3992 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003993 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00003994 reportParseError("`noreorder' must be set before `nomacro'");
3995 return false;
3996 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003997 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003998 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003999 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004000 return false;
4001}
Jack Carterd76b2372013-03-21 21:44:16 +00004002
Daniel Sanders44934432014-08-07 12:03:36 +00004003bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004004 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004005 Parser.Lex();
4006
4007 // If this is not the end of the statement, report an error.
4008 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004009 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004010
4011 setFeatureBits(Mips::FeatureMSA, "msa");
4012 getTargetStreamer().emitDirectiveSetMsa();
4013 return false;
4014}
4015
4016bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004017 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004018 Parser.Lex();
4019
4020 // If this is not the end of the statement, report an error.
4021 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004022 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004023
4024 clearFeatureBits(Mips::FeatureMSA, "msa");
4025 getTargetStreamer().emitDirectiveSetNoMsa();
4026 return false;
4027}
4028
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004029bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004030 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004031 Parser.Lex(); // Eat "nodsp".
4032
4033 // If this is not the end of the statement, report an error.
4034 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4035 reportParseError("unexpected token, expected end of statement");
4036 return false;
4037 }
4038
4039 clearFeatureBits(Mips::FeatureDSP, "dsp");
4040 getTargetStreamer().emitDirectiveSetNoDsp();
4041 return false;
4042}
4043
Toma Tabacucc2502d2014-11-04 17:18:07 +00004044bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004045 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004046 Parser.Lex(); // Eat "mips16".
4047
Jack Carter39536722014-01-22 23:08:42 +00004048 // If this is not the end of the statement, report an error.
4049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004050 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004051 return false;
4052 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004053
4054 setFeatureBits(Mips::FeatureMips16, "mips16");
4055 getTargetStreamer().emitDirectiveSetMips16();
4056 Parser.Lex(); // Consume the EndOfStatement.
4057 return false;
4058}
4059
4060bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004061 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004062 Parser.Lex(); // Eat "nomips16".
4063
4064 // If this is not the end of the statement, report an error.
4065 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4066 reportParseError("unexpected token, expected end of statement");
4067 return false;
4068 }
4069
4070 clearFeatureBits(Mips::FeatureMips16, "mips16");
4071 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004072 Parser.Lex(); // Consume the EndOfStatement.
4073 return false;
4074}
4075
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004076bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004077 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004078 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004079 // Line can be: .set fp=32
4080 // .set fp=xx
4081 // .set fp=64
4082 Parser.Lex(); // Eat fp token
4083 AsmToken Tok = Parser.getTok();
4084 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004085 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004086 return false;
4087 }
4088 Parser.Lex(); // Eat '=' token.
4089 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004090
4091 if (!parseFpABIValue(FpAbiVal, ".set"))
4092 return false;
4093
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004095 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004096 return false;
4097 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004098 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004099 Parser.Lex(); // Consume the EndOfStatement.
4100 return false;
4101}
4102
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004103bool MipsAsmParser::parseSetOddSPRegDirective() {
4104 MCAsmParser &Parser = getParser();
4105
4106 Parser.Lex(); // Eat "oddspreg".
4107 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4108 reportParseError("unexpected token, expected end of statement");
4109 return false;
4110 }
4111
4112 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4113 getTargetStreamer().emitDirectiveSetOddSPReg();
4114 return false;
4115}
4116
4117bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4118 MCAsmParser &Parser = getParser();
4119
4120 Parser.Lex(); // Eat "nooddspreg".
4121 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4122 reportParseError("unexpected token, expected end of statement");
4123 return false;
4124 }
4125
4126 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4127 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4128 return false;
4129}
4130
Toma Tabacu9db22db2014-09-09 10:15:38 +00004131bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004132 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004133 SMLoc Loc = getLexer().getLoc();
4134
4135 Parser.Lex();
4136 if (getLexer().isNot(AsmToken::EndOfStatement))
4137 return reportParseError("unexpected token, expected end of statement");
4138
4139 // Always keep an element on the options "stack" to prevent the user
4140 // from changing the initial options. This is how we remember them.
4141 if (AssemblerOptions.size() == 2)
4142 return reportParseError(Loc, ".set pop with no .set push");
4143
4144 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004145 setAvailableFeatures(
4146 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4147 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004148
4149 getTargetStreamer().emitDirectiveSetPop();
4150 return false;
4151}
4152
4153bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004154 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004155 Parser.Lex();
4156 if (getLexer().isNot(AsmToken::EndOfStatement))
4157 return reportParseError("unexpected token, expected end of statement");
4158
4159 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004160 AssemblerOptions.push_back(
4161 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004162
4163 getTargetStreamer().emitDirectiveSetPush();
4164 return false;
4165}
4166
Toma Tabacu29696502015-06-02 09:48:04 +00004167bool MipsAsmParser::parseSetSoftFloatDirective() {
4168 MCAsmParser &Parser = getParser();
4169 Parser.Lex();
4170 if (getLexer().isNot(AsmToken::EndOfStatement))
4171 return reportParseError("unexpected token, expected end of statement");
4172
4173 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4174 getTargetStreamer().emitDirectiveSetSoftFloat();
4175 return false;
4176}
4177
4178bool MipsAsmParser::parseSetHardFloatDirective() {
4179 MCAsmParser &Parser = getParser();
4180 Parser.Lex();
4181 if (getLexer().isNot(AsmToken::EndOfStatement))
4182 return reportParseError("unexpected token, expected end of statement");
4183
4184 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4185 getTargetStreamer().emitDirectiveSetHardFloat();
4186 return false;
4187}
4188
Jack Carterd76b2372013-03-21 21:44:16 +00004189bool MipsAsmParser::parseSetAssignment() {
4190 StringRef Name;
4191 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004192 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004193
4194 if (Parser.parseIdentifier(Name))
4195 reportParseError("expected identifier after .set");
4196
4197 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004198 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004199 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004200
Jack Carter3b2c96e2014-01-22 23:31:38 +00004201 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004202 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004203
Jim Grosbach6f482002015-05-18 18:43:14 +00004204 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004205 Sym->setVariableValue(Value);
4206
4207 return false;
4208}
Jack Carterd0bd6422013-04-18 00:41:53 +00004209
Toma Tabacu26647792014-09-09 12:52:14 +00004210bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004211 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004212 Parser.Lex();
4213 if (getLexer().isNot(AsmToken::EndOfStatement))
4214 return reportParseError("unexpected token, expected end of statement");
4215
4216 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004217 setAvailableFeatures(
4218 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4219 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004220 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4221
4222 getTargetStreamer().emitDirectiveSetMips0();
4223 return false;
4224}
4225
Toma Tabacu85618b32014-08-19 14:22:52 +00004226bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004227 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004228 Parser.Lex();
4229 if (getLexer().isNot(AsmToken::Equal))
4230 return reportParseError("unexpected token, expected equals sign");
4231
4232 Parser.Lex();
4233 StringRef Arch;
4234 if (Parser.parseIdentifier(Arch))
4235 return reportParseError("expected arch identifier");
4236
4237 StringRef ArchFeatureName =
4238 StringSwitch<StringRef>(Arch)
4239 .Case("mips1", "mips1")
4240 .Case("mips2", "mips2")
4241 .Case("mips3", "mips3")
4242 .Case("mips4", "mips4")
4243 .Case("mips5", "mips5")
4244 .Case("mips32", "mips32")
4245 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004246 .Case("mips32r3", "mips32r3")
4247 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004248 .Case("mips32r6", "mips32r6")
4249 .Case("mips64", "mips64")
4250 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004251 .Case("mips64r3", "mips64r3")
4252 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004253 .Case("mips64r6", "mips64r6")
4254 .Case("cnmips", "cnmips")
4255 .Case("r4000", "mips3") // This is an implementation of Mips3.
4256 .Default("");
4257
4258 if (ArchFeatureName.empty())
4259 return reportParseError("unsupported architecture");
4260
4261 selectArch(ArchFeatureName);
4262 getTargetStreamer().emitDirectiveSetArch(Arch);
4263 return false;
4264}
4265
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004266bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004267 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004268 Parser.Lex();
4269 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004270 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004271
Matheus Almeida2852af82014-04-22 10:15:54 +00004272 switch (Feature) {
4273 default:
4274 llvm_unreachable("Unimplemented feature");
4275 case Mips::FeatureDSP:
4276 setFeatureBits(Mips::FeatureDSP, "dsp");
4277 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004278 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004279 case Mips::FeatureMicroMips:
4280 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004281 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004282 case Mips::FeatureMips1:
4283 selectArch("mips1");
4284 getTargetStreamer().emitDirectiveSetMips1();
4285 break;
4286 case Mips::FeatureMips2:
4287 selectArch("mips2");
4288 getTargetStreamer().emitDirectiveSetMips2();
4289 break;
4290 case Mips::FeatureMips3:
4291 selectArch("mips3");
4292 getTargetStreamer().emitDirectiveSetMips3();
4293 break;
4294 case Mips::FeatureMips4:
4295 selectArch("mips4");
4296 getTargetStreamer().emitDirectiveSetMips4();
4297 break;
4298 case Mips::FeatureMips5:
4299 selectArch("mips5");
4300 getTargetStreamer().emitDirectiveSetMips5();
4301 break;
4302 case Mips::FeatureMips32:
4303 selectArch("mips32");
4304 getTargetStreamer().emitDirectiveSetMips32();
4305 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004306 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004307 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004308 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004309 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004310 case Mips::FeatureMips32r3:
4311 selectArch("mips32r3");
4312 getTargetStreamer().emitDirectiveSetMips32R3();
4313 break;
4314 case Mips::FeatureMips32r5:
4315 selectArch("mips32r5");
4316 getTargetStreamer().emitDirectiveSetMips32R5();
4317 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004318 case Mips::FeatureMips32r6:
4319 selectArch("mips32r6");
4320 getTargetStreamer().emitDirectiveSetMips32R6();
4321 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004322 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004323 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004324 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004325 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004326 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004327 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004328 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004329 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004330 case Mips::FeatureMips64r3:
4331 selectArch("mips64r3");
4332 getTargetStreamer().emitDirectiveSetMips64R3();
4333 break;
4334 case Mips::FeatureMips64r5:
4335 selectArch("mips64r5");
4336 getTargetStreamer().emitDirectiveSetMips64R5();
4337 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004338 case Mips::FeatureMips64r6:
4339 selectArch("mips64r6");
4340 getTargetStreamer().emitDirectiveSetMips64R6();
4341 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004342 }
4343 return false;
4344}
4345
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004346bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004347 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004348 if (getLexer().isNot(AsmToken::Comma)) {
4349 SMLoc Loc = getLexer().getLoc();
4350 Parser.eatToEndOfStatement();
4351 return Error(Loc, ErrorStr);
4352 }
4353
Matheus Almeida2852af82014-04-22 10:15:54 +00004354 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004355 return true;
4356}
4357
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004358bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004359 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004360 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004361
Toma Tabacudde4c462014-11-06 10:02:45 +00004362 if (inMips16Mode()) {
4363 reportParseError(".cpload is not supported in Mips16 mode");
4364 return false;
4365 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004366
David Blaikie960ea3f2014-06-08 16:18:35 +00004367 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004368 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004369 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4370 reportParseError("expected register containing function address");
4371 return false;
4372 }
4373
David Blaikie960ea3f2014-06-08 16:18:35 +00004374 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4375 if (!RegOpnd.isGPRAsmReg()) {
4376 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004377 return false;
4378 }
4379
Toma Tabacudde4c462014-11-06 10:02:45 +00004380 // If this is not the end of the statement, report an error.
4381 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4382 reportParseError("unexpected token, expected end of statement");
4383 return false;
4384 }
4385
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004386 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004387 return false;
4388}
4389
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004390bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004391 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004392 unsigned FuncReg;
4393 unsigned Save;
4394 bool SaveIsReg = true;
4395
Matheus Almeida7e815762014-06-18 13:08:59 +00004396 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004397 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004398 if (ResTy == MatchOperand_NoMatch) {
4399 reportParseError("expected register containing function address");
4400 Parser.eatToEndOfStatement();
4401 return false;
4402 }
4403
4404 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4405 if (!FuncRegOpnd.isGPRAsmReg()) {
4406 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4407 Parser.eatToEndOfStatement();
4408 return false;
4409 }
4410
4411 FuncReg = FuncRegOpnd.getGPR32Reg();
4412 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004413
Toma Tabacu65f10572014-09-16 15:00:52 +00004414 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004415 return true;
4416
Toma Tabacu13964452014-09-04 13:23:44 +00004417 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004418 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004419 const AsmToken &Tok = Parser.getTok();
4420 if (Tok.is(AsmToken::Integer)) {
4421 Save = Tok.getIntVal();
4422 SaveIsReg = false;
4423 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004424 } else {
4425 reportParseError("expected save register or stack offset");
4426 Parser.eatToEndOfStatement();
4427 return false;
4428 }
4429 } else {
4430 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4431 if (!SaveOpnd.isGPRAsmReg()) {
4432 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4433 Parser.eatToEndOfStatement();
4434 return false;
4435 }
4436 Save = SaveOpnd.getGPR32Reg();
4437 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004438
Toma Tabacu65f10572014-09-16 15:00:52 +00004439 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004440 return true;
4441
Toma Tabacu8874eac2015-02-18 13:46:53 +00004442 const MCExpr *Expr;
4443 if (Parser.parseExpression(Expr)) {
4444 reportParseError("expected expression");
4445 return false;
4446 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004447
Toma Tabacu8874eac2015-02-18 13:46:53 +00004448 if (Expr->getKind() != MCExpr::SymbolRef) {
4449 reportParseError("expected symbol");
4450 return false;
4451 }
4452 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4453
4454 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4455 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004456 return false;
4457}
4458
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004459bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004460 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004461 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4462 const AsmToken &Tok = Parser.getTok();
4463
4464 if (Tok.getString() == "2008") {
4465 Parser.Lex();
4466 getTargetStreamer().emitDirectiveNaN2008();
4467 return false;
4468 } else if (Tok.getString() == "legacy") {
4469 Parser.Lex();
4470 getTargetStreamer().emitDirectiveNaNLegacy();
4471 return false;
4472 }
4473 }
4474 // If we don't recognize the option passed to the .nan
4475 // directive (e.g. no option or unknown option), emit an error.
4476 reportParseError("invalid option in .nan directive");
4477 return false;
4478}
4479
Jack Carter0b744b32012-10-04 02:29:46 +00004480bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004481 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004482 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004483 const AsmToken &Tok = Parser.getTok();
4484
4485 if (Tok.getString() == "noat") {
4486 return parseSetNoAtDirective();
4487 } else if (Tok.getString() == "at") {
4488 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004489 } else if (Tok.getString() == "arch") {
4490 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004491 } else if (Tok.getString() == "fp") {
4492 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004493 } else if (Tok.getString() == "oddspreg") {
4494 return parseSetOddSPRegDirective();
4495 } else if (Tok.getString() == "nooddspreg") {
4496 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004497 } else if (Tok.getString() == "pop") {
4498 return parseSetPopDirective();
4499 } else if (Tok.getString() == "push") {
4500 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004501 } else if (Tok.getString() == "reorder") {
4502 return parseSetReorderDirective();
4503 } else if (Tok.getString() == "noreorder") {
4504 return parseSetNoReorderDirective();
4505 } else if (Tok.getString() == "macro") {
4506 return parseSetMacroDirective();
4507 } else if (Tok.getString() == "nomacro") {
4508 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004509 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004510 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004511 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004512 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004513 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004514 getTargetStreamer().emitDirectiveSetNoMicroMips();
4515 Parser.eatToEndOfStatement();
4516 return false;
4517 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004518 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004519 } else if (Tok.getString() == "mips0") {
4520 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004521 } else if (Tok.getString() == "mips1") {
4522 return parseSetFeature(Mips::FeatureMips1);
4523 } else if (Tok.getString() == "mips2") {
4524 return parseSetFeature(Mips::FeatureMips2);
4525 } else if (Tok.getString() == "mips3") {
4526 return parseSetFeature(Mips::FeatureMips3);
4527 } else if (Tok.getString() == "mips4") {
4528 return parseSetFeature(Mips::FeatureMips4);
4529 } else if (Tok.getString() == "mips5") {
4530 return parseSetFeature(Mips::FeatureMips5);
4531 } else if (Tok.getString() == "mips32") {
4532 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004533 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004534 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004535 } else if (Tok.getString() == "mips32r3") {
4536 return parseSetFeature(Mips::FeatureMips32r3);
4537 } else if (Tok.getString() == "mips32r5") {
4538 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004539 } else if (Tok.getString() == "mips32r6") {
4540 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004541 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004542 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004543 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004544 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004545 } else if (Tok.getString() == "mips64r3") {
4546 return parseSetFeature(Mips::FeatureMips64r3);
4547 } else if (Tok.getString() == "mips64r5") {
4548 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004549 } else if (Tok.getString() == "mips64r6") {
4550 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004551 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004552 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004553 } else if (Tok.getString() == "nodsp") {
4554 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004555 } else if (Tok.getString() == "msa") {
4556 return parseSetMsaDirective();
4557 } else if (Tok.getString() == "nomsa") {
4558 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004559 } else if (Tok.getString() == "softfloat") {
4560 return parseSetSoftFloatDirective();
4561 } else if (Tok.getString() == "hardfloat") {
4562 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004563 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004564 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004565 parseSetAssignment();
4566 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004567 }
Jack Carter07c818d2013-01-25 01:31:34 +00004568
Jack Carter0b744b32012-10-04 02:29:46 +00004569 return true;
4570}
4571
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004572/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004573/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004574bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004575 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004576 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4577 for (;;) {
4578 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004579 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004580 return true;
4581
4582 getParser().getStreamer().EmitValue(Value, Size);
4583
4584 if (getLexer().is(AsmToken::EndOfStatement))
4585 break;
4586
Jack Carter07c818d2013-01-25 01:31:34 +00004587 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004588 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004589 Parser.Lex();
4590 }
4591 }
4592
4593 Parser.Lex();
4594 return false;
4595}
4596
Vladimir Medic4c299852013-11-06 11:27:05 +00004597/// parseDirectiveGpWord
4598/// ::= .gpword local_sym
4599bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004600 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004601 const MCExpr *Value;
4602 // EmitGPRel32Value requires an expression, so we are using base class
4603 // method to evaluate the expression.
4604 if (getParser().parseExpression(Value))
4605 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004606 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004607
Vladimir Medice10c1122013-11-13 13:18:04 +00004608 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004609 return Error(getLexer().getLoc(),
4610 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004611 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004612 return false;
4613}
4614
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004615/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004616/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004617bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004618 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004619 const MCExpr *Value;
4620 // EmitGPRel64Value requires an expression, so we are using base class
4621 // method to evaluate the expression.
4622 if (getParser().parseExpression(Value))
4623 return true;
4624 getParser().getStreamer().EmitGPRel64Value(Value);
4625
4626 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004627 return Error(getLexer().getLoc(),
4628 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004629 Parser.Lex(); // Eat EndOfStatement token.
4630 return false;
4631}
4632
Jack Carter0cd3c192014-01-06 23:27:31 +00004633bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004634 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004635 // Get the option token.
4636 AsmToken Tok = Parser.getTok();
4637 // At the moment only identifiers are supported.
4638 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004639 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004640 Parser.eatToEndOfStatement();
4641 return false;
4642 }
4643
4644 StringRef Option = Tok.getIdentifier();
4645
4646 if (Option == "pic0") {
4647 getTargetStreamer().emitDirectiveOptionPic0();
4648 Parser.Lex();
4649 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4650 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004651 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004652 Parser.eatToEndOfStatement();
4653 }
4654 return false;
4655 }
4656
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004657 if (Option == "pic2") {
4658 getTargetStreamer().emitDirectiveOptionPic2();
4659 Parser.Lex();
4660 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4661 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004662 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004663 Parser.eatToEndOfStatement();
4664 }
4665 return false;
4666 }
4667
Jack Carter0cd3c192014-01-06 23:27:31 +00004668 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004669 Warning(Parser.getTok().getLoc(),
4670 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004671 Parser.eatToEndOfStatement();
4672 return false;
4673}
4674
Toma Tabacu9ca50962015-04-16 09:53:47 +00004675/// parseInsnDirective
4676/// ::= .insn
4677bool MipsAsmParser::parseInsnDirective() {
4678 // If this is not the end of the statement, report an error.
4679 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4680 reportParseError("unexpected token, expected end of statement");
4681 return false;
4682 }
4683
4684 // The actual label marking happens in
4685 // MipsELFStreamer::createPendingLabelRelocs().
4686 getTargetStreamer().emitDirectiveInsn();
4687
4688 getParser().Lex(); // Eat EndOfStatement token.
4689 return false;
4690}
4691
Daniel Sanders7e527422014-07-10 13:38:23 +00004692/// parseDirectiveModule
4693/// ::= .module oddspreg
4694/// ::= .module nooddspreg
4695/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004696bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004697 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004698 MCAsmLexer &Lexer = getLexer();
4699 SMLoc L = Lexer.getLoc();
4700
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004701 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004702 // TODO : get a better message.
4703 reportParseError(".module directive must appear before any code");
4704 return false;
4705 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004706
Toma Tabacuc405c822015-01-23 10:40:19 +00004707 StringRef Option;
4708 if (Parser.parseIdentifier(Option)) {
4709 reportParseError("expected .module option identifier");
4710 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004711 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004712
Toma Tabacuc405c822015-01-23 10:40:19 +00004713 if (Option == "oddspreg") {
Toma Tabacuc405c822015-01-23 10:40:19 +00004714 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4715
Toma Tabacu3c499582015-06-25 10:56:57 +00004716 // Synchronize the abiflags information with the FeatureBits information we
4717 // changed above.
4718 getTargetStreamer().updateABIInfo(*this);
4719
4720 // If printing assembly, use the recently updated abiflags information.
4721 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4722 // emitted at the end).
4723 getTargetStreamer().emitDirectiveModuleOddSPReg();
4724
Toma Tabacuc405c822015-01-23 10:40:19 +00004725 // If this is not the end of the statement, report an error.
4726 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4727 reportParseError("unexpected token, expected end of statement");
4728 return false;
4729 }
4730
4731 return false; // parseDirectiveModule has finished successfully.
4732 } else if (Option == "nooddspreg") {
4733 if (!isABI_O32()) {
4734 Error(L, "'.module nooddspreg' requires the O32 ABI");
4735 return false;
4736 }
4737
Toma Tabacuc405c822015-01-23 10:40:19 +00004738 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4739
Toma Tabacu3c499582015-06-25 10:56:57 +00004740 // Synchronize the abiflags information with the FeatureBits information we
4741 // changed above.
4742 getTargetStreamer().updateABIInfo(*this);
4743
4744 // If printing assembly, use the recently updated abiflags information.
4745 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4746 // emitted at the end).
4747 getTargetStreamer().emitDirectiveModuleOddSPReg();
4748
Toma Tabacuc405c822015-01-23 10:40:19 +00004749 // If this is not the end of the statement, report an error.
4750 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4751 reportParseError("unexpected token, expected end of statement");
4752 return false;
4753 }
4754
4755 return false; // parseDirectiveModule has finished successfully.
4756 } else if (Option == "fp") {
4757 return parseDirectiveModuleFP();
4758 } else {
4759 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4760 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004761}
4762
4763/// parseDirectiveModuleFP
4764/// ::= =32
4765/// ::= =xx
4766/// ::= =64
4767bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004768 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004769 MCAsmLexer &Lexer = getLexer();
4770
4771 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004772 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004773 return false;
4774 }
4775 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004776
Daniel Sanders7e527422014-07-10 13:38:23 +00004777 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004778 if (!parseFpABIValue(FpABI, ".module"))
4779 return false;
4780
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004781 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004782 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004783 return false;
4784 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004785
Toma Tabacua64e5402015-06-25 12:44:38 +00004786 // Synchronize the abiflags information with the FeatureBits information we
4787 // changed above.
4788 getTargetStreamer().updateABIInfo(*this);
4789
4790 // If printing assembly, use the recently updated abiflags information.
4791 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4792 // emitted at the end).
4793 getTargetStreamer().emitDirectiveModuleFP();
4794
Daniel Sanders7e527422014-07-10 13:38:23 +00004795 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004796 return false;
4797}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004798
Daniel Sanders7e527422014-07-10 13:38:23 +00004799bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004800 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004801 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004802 MCAsmLexer &Lexer = getLexer();
4803
4804 if (Lexer.is(AsmToken::Identifier)) {
4805 StringRef Value = Parser.getTok().getString();
4806 Parser.Lex();
4807
4808 if (Value != "xx") {
4809 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4810 return false;
4811 }
4812
4813 if (!isABI_O32()) {
4814 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4815 return false;
4816 }
4817
Daniel Sanders7e527422014-07-10 13:38:23 +00004818 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacua64e5402015-06-25 12:44:38 +00004819 setFeatureBits(Mips::FeatureFPXX, "fpxx");
4820 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004821 return true;
4822 }
4823
4824 if (Lexer.is(AsmToken::Integer)) {
4825 unsigned Value = Parser.getTok().getIntVal();
4826 Parser.Lex();
4827
4828 if (Value != 32 && Value != 64) {
4829 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4830 return false;
4831 }
4832
4833 if (Value == 32) {
4834 if (!isABI_O32()) {
4835 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4836 return false;
4837 }
4838
Daniel Sanders7e527422014-07-10 13:38:23 +00004839 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacua64e5402015-06-25 12:44:38 +00004840 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4841 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
4842 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00004843 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacua64e5402015-06-25 12:44:38 +00004844 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4845 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
4846 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004847
Daniel Sanders7e527422014-07-10 13:38:23 +00004848 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004849 }
4850
4851 return false;
4852}
4853
Jack Carter0b744b32012-10-04 02:29:46 +00004854bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004855 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004856 StringRef IDVal = DirectiveID.getString();
4857
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004858 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004859 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004860 if (IDVal == ".dword") {
4861 parseDataDirective(8, DirectiveID.getLoc());
4862 return false;
4863 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004864 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004865 StringRef SymbolName;
4866
4867 if (Parser.parseIdentifier(SymbolName)) {
4868 reportParseError("expected identifier after .ent");
4869 return false;
4870 }
4871
4872 // There's an undocumented extension that allows an integer to
4873 // follow the name of the procedure which AFAICS is ignored by GAS.
4874 // Example: .ent foo,2
4875 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4876 if (getLexer().isNot(AsmToken::Comma)) {
4877 // Even though we accept this undocumented extension for compatibility
4878 // reasons, the additional integer argument does not actually change
4879 // the behaviour of the '.ent' directive, so we would like to discourage
4880 // its use. We do this by not referring to the extended version in
4881 // error messages which are not directly related to its use.
4882 reportParseError("unexpected token, expected end of statement");
4883 return false;
4884 }
4885 Parser.Lex(); // Eat the comma.
4886 const MCExpr *DummyNumber;
4887 int64_t DummyNumberVal;
4888 // If the user was explicitly trying to use the extended version,
4889 // we still give helpful extension-related error messages.
4890 if (Parser.parseExpression(DummyNumber)) {
4891 reportParseError("expected number after comma");
4892 return false;
4893 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004894 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004895 reportParseError("expected an absolute expression after comma");
4896 return false;
4897 }
4898 }
4899
4900 // If this is not the end of the statement, report an error.
4901 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4902 reportParseError("unexpected token, expected end of statement");
4903 return false;
4904 }
4905
Jim Grosbach6f482002015-05-18 18:43:14 +00004906 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004907
4908 getTargetStreamer().emitDirectiveEnt(*Sym);
4909 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004910 return false;
4911 }
4912
Jack Carter07c818d2013-01-25 01:31:34 +00004913 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004914 StringRef SymbolName;
4915
4916 if (Parser.parseIdentifier(SymbolName)) {
4917 reportParseError("expected identifier after .end");
4918 return false;
4919 }
4920
4921 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4922 reportParseError("unexpected token, expected end of statement");
4923 return false;
4924 }
4925
4926 if (CurrentFn == nullptr) {
4927 reportParseError(".end used without .ent");
4928 return false;
4929 }
4930
4931 if ((SymbolName != CurrentFn->getName())) {
4932 reportParseError(".end symbol does not match .ent symbol");
4933 return false;
4934 }
4935
4936 getTargetStreamer().emitDirectiveEnd(SymbolName);
4937 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00004938 return false;
4939 }
4940
Jack Carter07c818d2013-01-25 01:31:34 +00004941 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004942 // .frame $stack_reg, frame_size_in_bytes, $return_reg
4943 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004944 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004945 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4946 reportParseError("expected stack register");
4947 return false;
4948 }
4949
4950 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4951 if (!StackRegOpnd.isGPRAsmReg()) {
4952 reportParseError(StackRegOpnd.getStartLoc(),
4953 "expected general purpose register");
4954 return false;
4955 }
4956 unsigned StackReg = StackRegOpnd.getGPR32Reg();
4957
4958 if (Parser.getTok().is(AsmToken::Comma))
4959 Parser.Lex();
4960 else {
4961 reportParseError("unexpected token, expected comma");
4962 return false;
4963 }
4964
4965 // Parse the frame size.
4966 const MCExpr *FrameSize;
4967 int64_t FrameSizeVal;
4968
4969 if (Parser.parseExpression(FrameSize)) {
4970 reportParseError("expected frame size value");
4971 return false;
4972 }
4973
Jim Grosbach13760bd2015-05-30 01:25:56 +00004974 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004975 reportParseError("frame size not an absolute expression");
4976 return false;
4977 }
4978
4979 if (Parser.getTok().is(AsmToken::Comma))
4980 Parser.Lex();
4981 else {
4982 reportParseError("unexpected token, expected comma");
4983 return false;
4984 }
4985
4986 // Parse the return register.
4987 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00004988 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004989 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4990 reportParseError("expected return register");
4991 return false;
4992 }
4993
4994 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4995 if (!ReturnRegOpnd.isGPRAsmReg()) {
4996 reportParseError(ReturnRegOpnd.getStartLoc(),
4997 "expected general purpose register");
4998 return false;
4999 }
5000
5001 // If this is not the end of the statement, report an error.
5002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5003 reportParseError("unexpected token, expected end of statement");
5004 return false;
5005 }
5006
5007 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5008 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005009 return false;
5010 }
5011
Jack Carter07c818d2013-01-25 01:31:34 +00005012 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005013 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005014 }
5015
Daniel Sandersd97a6342014-08-13 10:07:34 +00005016 if (IDVal == ".mask" || IDVal == ".fmask") {
5017 // .mask bitmask, frame_offset
5018 // bitmask: One bit for each register used.
5019 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5020 // first register is expected to be saved.
5021 // Examples:
5022 // .mask 0x80000000, -4
5023 // .fmask 0x80000000, -4
5024 //
Jack Carterbe332172012-09-07 00:48:02 +00005025
Daniel Sandersd97a6342014-08-13 10:07:34 +00005026 // Parse the bitmask
5027 const MCExpr *BitMask;
5028 int64_t BitMaskVal;
5029
5030 if (Parser.parseExpression(BitMask)) {
5031 reportParseError("expected bitmask value");
5032 return false;
5033 }
5034
Jim Grosbach13760bd2015-05-30 01:25:56 +00005035 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005036 reportParseError("bitmask not an absolute expression");
5037 return false;
5038 }
5039
5040 if (Parser.getTok().is(AsmToken::Comma))
5041 Parser.Lex();
5042 else {
5043 reportParseError("unexpected token, expected comma");
5044 return false;
5045 }
5046
5047 // Parse the frame_offset
5048 const MCExpr *FrameOffset;
5049 int64_t FrameOffsetVal;
5050
5051 if (Parser.parseExpression(FrameOffset)) {
5052 reportParseError("expected frame offset value");
5053 return false;
5054 }
5055
Jim Grosbach13760bd2015-05-30 01:25:56 +00005056 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005057 reportParseError("frame offset not an absolute expression");
5058 return false;
5059 }
5060
5061 // If this is not the end of the statement, report an error.
5062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5063 reportParseError("unexpected token, expected end of statement");
5064 return false;
5065 }
5066
5067 if (IDVal == ".mask")
5068 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5069 else
5070 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005071 return false;
5072 }
5073
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005074 if (IDVal == ".nan")
5075 return parseDirectiveNaN();
5076
Jack Carter07c818d2013-01-25 01:31:34 +00005077 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005078 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005079 return false;
5080 }
5081
Rafael Espindolab59fb732014-03-28 18:50:26 +00005082 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005083 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005084 return false;
5085 }
5086
Jack Carter07c818d2013-01-25 01:31:34 +00005087 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005088 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005089 return false;
5090 }
5091
Jack Carter0cd3c192014-01-06 23:27:31 +00005092 if (IDVal == ".option")
5093 return parseDirectiveOption();
5094
5095 if (IDVal == ".abicalls") {
5096 getTargetStreamer().emitDirectiveAbiCalls();
5097 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005098 Error(Parser.getTok().getLoc(),
5099 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005100 // Clear line
5101 Parser.eatToEndOfStatement();
5102 }
5103 return false;
5104 }
5105
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005106 if (IDVal == ".cpsetup")
5107 return parseDirectiveCPSetup();
5108
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005109 if (IDVal == ".module")
5110 return parseDirectiveModule();
5111
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005112 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5113 return parseInternalDirectiveReallowModule();
5114
Toma Tabacu9ca50962015-04-16 09:53:47 +00005115 if (IDVal == ".insn")
5116 return parseInsnDirective();
5117
Rafael Espindola870c4e92012-01-11 03:56:41 +00005118 return true;
5119}
5120
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005121bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5122 // If this is not the end of the statement, report an error.
5123 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5124 reportParseError("unexpected token, expected end of statement");
5125 return false;
5126 }
5127
5128 getTargetStreamer().reallowModuleDirective();
5129
5130 getParser().Lex(); // Eat EndOfStatement token.
5131 return false;
5132}
5133
Rafael Espindola870c4e92012-01-11 03:56:41 +00005134extern "C" void LLVMInitializeMipsAsmParser() {
5135 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5136 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5137 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5138 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5139}
Jack Carterb4dbc172012-09-05 23:34:03 +00005140
5141#define GET_REGISTER_MATCHER
5142#define GET_MATCHER_IMPLEMENTATION
5143#include "MipsGenAsmMatcher.inc"