blob: f40d33c8eaa742101bca546a96d72f627c543b56 [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
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000012#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000013#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Hrvoje Vargadbe4d962016-09-08 07:41:43 +000015#include "MCTargetDesc/MipsBaseInfo.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Triple.h"
21#include "llvm/ADT/Twine.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000025#include "llvm/MC/MCInstrDesc.h"
26#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000027#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000028#include "llvm/MC/MCParser/MCAsmParser.h"
29#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000030#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000031#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000032#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000033#include "llvm/MC/MCStreamer.h"
34#include "llvm/MC/MCSubtargetInfo.h"
35#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000036#include "llvm/MC/MCSymbolELF.h"
37#include "llvm/MC/MCValue.h"
38#include "llvm/MC/SubtargetFeature.h"
39#include "llvm/Support/Casting.h"
40#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000041#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000042#include "llvm/Support/ELF.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000043#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000044#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000045#include "llvm/Support/raw_ostream.h"
46#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000049#include <algorithm>
50#include <cassert>
51#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000052#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000053#include <string>
54#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000055
56using namespace llvm;
57
Chandler Carruthe96dd892014-04-21 22:55:11 +000058#define DEBUG_TYPE "mips-asm-parser"
59
Joey Gouly0e76fa72013-09-12 10:28:05 +000060namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000061
Joey Gouly0e76fa72013-09-12 10:28:05 +000062class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000063
64} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000065
Rafael Espindola870c4e92012-01-11 03:56:41 +000066namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000067
Jack Carter0b744b32012-10-04 02:29:46 +000068class MipsAssemblerOptions {
69public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000070 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000073 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000074 Reorder = Opts->isReorder();
75 Macro = Opts->isMacro();
76 Features = Opts->getFeatures();
77 }
78
Toma Tabacub19cf202015-04-27 13:12:59 +000079 unsigned getATRegIndex() const { return ATReg; }
80 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000081 if (Reg > 31)
82 return false;
83
84 ATReg = Reg;
85 return true;
86 }
Jack Carter0b744b32012-10-04 02:29:46 +000087
Toma Tabacu9db22db2014-09-09 10:15:38 +000088 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000089 void setReorder() { Reorder = true; }
90 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000091
Toma Tabacu9db22db2014-09-09 10:15:38 +000092 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000093 void setMacro() { Macro = true; }
94 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000095
Toma Tabacu465acfd2015-06-09 13:33:26 +000096 const FeatureBitset &getFeatures() const { return Features; }
97 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000098
Daniel Sandersf0df2212014-08-04 12:20:00 +000099 // Set of features that are either architecture features or referenced
100 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
101 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
102 // The reason we need this mask is explained in the selectArch function.
103 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000104 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000105
Jack Carter0b744b32012-10-04 02:29:46 +0000106private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000107 unsigned ATReg = 1;
108 bool Reorder = true;
109 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000110 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000111};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000112
113} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000114
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000115const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
116 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
117 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
118 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
119 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
120 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
121 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
122 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
123 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
124};
125
Jack Carter0b744b32012-10-04 02:29:46 +0000126namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000127
Rafael Espindola870c4e92012-01-11 03:56:41 +0000128class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000129 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000130 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000131 return static_cast<MipsTargetStreamer &>(TS);
132 }
133
Eric Christophera5762812015-01-26 17:33:46 +0000134 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000135 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000136 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
137 // nullptr, which indicates that no function is currently
138 // selected. This usually happens after an '.end func'
139 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000140 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000141 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000142 bool IsCpRestoreSet;
143 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000144 unsigned CpSaveLocation;
145 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
146 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000147
Daniel Sandersef638fe2014-10-03 15:37:37 +0000148 // Print a warning along with its fix-it message at the given range.
149 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
150 SMRange Range, bool ShowColors = true);
151
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000152#define GET_ASSEMBLER_HEADER
153#include "MipsGenAsmMatcher.inc"
154
Daniel Sandersc5537422016-07-27 13:49:44 +0000155 unsigned
156 checkEarlyTargetMatchPredicate(MCInst &Inst,
157 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000158 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
159
Chad Rosier49963552012-10-13 00:26:04 +0000160 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000161 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000162 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000163 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000164
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000165 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000166 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000169
Toma Tabacu13964452014-09-04 13:23:44 +0000170 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000171
David Blaikie960ea3f2014-06-08 16:18:35 +0000172 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
173 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000174
Craig Topper56c590a2014-04-29 07:58:02 +0000175 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000176
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000177 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
178 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000179 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000180 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000181 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
182 SMLoc S);
183 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
184 OperandMatchResultTy parseImm(OperandVector &Operands);
185 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
186 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000187 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
188 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
189 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000190
David Blaikie960ea3f2014-06-08 16:18:35 +0000191 bool searchSymbolAlias(OperandVector &Operands);
192
Toma Tabacu13964452014-09-04 13:23:44 +0000193 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000194
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000195 enum MacroExpanderResultTy {
196 MER_NotAMacro,
197 MER_Success,
198 MER_Fail,
199 };
Jack Carter30a59822012-10-04 04:03:53 +0000200
Matheus Almeida3813d572014-06-19 14:39:14 +0000201 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000202 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
203 MCStreamer &Out,
204 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000205
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000206 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000208
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000209 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000210 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000211 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212
Toma Tabacuf712ede2015-06-17 14:31:51 +0000213 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
214 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000216
Toma Tabacu00e98672015-05-01 12:19:27 +0000217 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000219
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000220 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
221 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000222 SMLoc IDLoc, MCStreamer &Out,
223 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000225 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
226 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000227
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000228 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000229 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
230
231 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI, bool IsImmOpnd);
233
234 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
238 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000239
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000240 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000242
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000243 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000251 const bool Signed);
252
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000253 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000254 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000255
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000256 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
257 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000258
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000259 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
260 const MCSubtargetInfo *STI);
261
262 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000264
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000265 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000266 MCStreamer &Out, const MCSubtargetInfo *STI);
267 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
268 const MCSubtargetInfo *STI);
269 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
270 const MCSubtargetInfo *STI);
271 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
272 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000273
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000274 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
275 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000276
Simon Dardisaff4d142016-10-18 14:28:00 +0000277 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
278 const MCSubtargetInfo *STI, bool IsLoad);
279
Simon Dardis43115a12016-11-21 20:30:41 +0000280 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
282
283 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
285
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000286 bool reportParseError(Twine ErrorMsg);
287 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000288
Jack Carterb5cf5902013-04-17 00:18:04 +0000289 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000290
291 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000292 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000293 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000294 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000295 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000296 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000297 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000298 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000299 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000300 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000301 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000302 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000303 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000304 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000305
306 bool parseSetAtDirective();
307 bool parseSetNoAtDirective();
308 bool parseSetMacroDirective();
309 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000310 bool parseSetMsaDirective();
311 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000312 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000313 bool parseSetReorderDirective();
314 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000315 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000316 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000317 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000318 bool parseSetOddSPRegDirective();
319 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000320 bool parseSetPopDirective();
321 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000322 bool parseSetSoftFloatDirective();
323 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000324
Jack Carterd76b2372013-03-21 21:44:16 +0000325 bool parseSetAssignment();
326
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000327 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000328 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000329 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000330 bool parseDirectiveDtpRelWord();
331 bool parseDirectiveDtpRelDWord();
332 bool parseDirectiveTpRelWord();
333 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000334 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000335 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000336 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
337 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000338
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000339 bool parseInternalDirectiveReallowModule();
340
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000341 bool eatComma(StringRef ErrorStr);
342
Jack Carter1ac53222013-02-20 23:11:17 +0000343 int matchCPURegisterName(StringRef Symbol);
344
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000345 int matchHWRegsRegisterName(StringRef Symbol);
346
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000347 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000348
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000349 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000350
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000351 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000352
Jack Carter5dc8ac92013-09-25 23:50:44 +0000353 int matchMSA128RegisterName(StringRef Name);
354
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000355 int matchMSA128CtrlRegisterName(StringRef Name);
356
Jack Carterd0bd6422013-04-18 00:41:53 +0000357 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000358
Toma Tabacu89a712b2015-04-15 10:48:56 +0000359 /// Returns the internal register number for the current AT. Also checks if
360 /// the current AT is unavailable (set to $0) and gives an error if it is.
361 /// This should be used in pseudo-instruction expansions which need AT.
362 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000363
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000364 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
365 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000366
367 // Helper function that checks if the value of a vector index is within the
368 // boundaries of accepted values for each RegisterKind
369 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
370 bool validateMSAIndex(int Val, int RegKind);
371
Daniel Sandersf0df2212014-08-04 12:20:00 +0000372 // Selects a new architecture by updating the FeatureBits with the necessary
373 // info including implied dependencies.
374 // Internally, it clears all the feature bits related to *any* architecture
375 // and selects the new one using the ToggleFeature functionality of the
376 // MCSubtargetInfo object that handles implied dependencies. The reason we
377 // clear all the arch related bits manually is because ToggleFeature only
378 // clears the features that imply the feature being cleared and not the
379 // features implied by the feature being cleared. This is easier to see
380 // with an example:
381 // --------------------------------------------------
382 // | Feature | Implies |
383 // | -------------------------------------------------|
384 // | FeatureMips1 | None |
385 // | FeatureMips2 | FeatureMips1 |
386 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
387 // | FeatureMips4 | FeatureMips3 |
388 // | ... | |
389 // --------------------------------------------------
390 //
391 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
392 // FeatureMipsGP64 | FeatureMips1)
393 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
394 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000395 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000396 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000397 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
398 STI.setFeatureBits(FeatureBits);
399 setAvailableFeatures(
400 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000401 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000402 }
403
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000404 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000405 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000406 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000407 setAvailableFeatures(
408 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000409 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000410 }
411 }
412
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000413 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000414 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000415 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000416 setAvailableFeatures(
417 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000418 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000419 }
420 }
421
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000422 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
423 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000424 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000425 }
426
427 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
428 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000429 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000430 }
431
Rafael Espindola870c4e92012-01-11 03:56:41 +0000432public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000433 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000434 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000435 Match_RequiresDifferentOperands,
436 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000437 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000438 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000439 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000440#define GET_OPERAND_DIAGNOSTIC_TYPES
441#include "MipsGenAsmMatcher.inc"
442#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000443 };
444
Akira Hatanakab11ef082015-11-14 06:35:56 +0000445 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000446 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000447 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000448 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
449 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000450 MCAsmParserExtension::Initialize(parser);
451
Toma Tabacu11e14a92015-04-21 11:50:52 +0000452 parser.addAliasForDirective(".asciiz", ".asciz");
453
Jack Carterb4dbc172012-09-05 23:34:03 +0000454 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000456
Toma Tabacu9db22db2014-09-09 10:15:38 +0000457 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000458 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000459 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000460
Toma Tabacu9db22db2014-09-09 10:15:38 +0000461 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000462 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000463 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000464
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 getTargetStreamer().updateABIInfo(*this);
466
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000467 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000468 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000469
470 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000471
Rafael Espindola699281c2016-05-18 11:58:50 +0000472 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000473
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000474 IsCpRestoreSet = false;
475 CpRestoreOffset = -1;
476
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000477 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000478 if ((TheTriple.getArch() == Triple::mips) ||
479 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000480 IsLittleEndian = false;
481 else
482 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000483 }
484
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000485 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
486 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
487
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000488 bool isGP64bit() const {
489 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
490 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000491
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 bool isFP64bit() const {
493 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
494 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000495
Eric Christophera5762812015-01-26 17:33:46 +0000496 const MipsABIInfo &getABI() const { return ABI; }
497 bool isABI_N32() const { return ABI.IsN32(); }
498 bool isABI_N64() const { return ABI.IsN64(); }
499 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000500 bool isABI_FPXX() const {
501 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
502 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000504 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000506 }
507
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000508 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000509 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000511
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000512 bool hasMips1() const {
513 return getSTI().getFeatureBits()[Mips::FeatureMips1];
514 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000515
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 bool hasMips2() const {
517 return getSTI().getFeatureBits()[Mips::FeatureMips2];
518 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000519
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 bool hasMips3() const {
521 return getSTI().getFeatureBits()[Mips::FeatureMips3];
522 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000523
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 bool hasMips4() const {
525 return getSTI().getFeatureBits()[Mips::FeatureMips4];
526 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000527
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000528 bool hasMips5() const {
529 return getSTI().getFeatureBits()[Mips::FeatureMips5];
530 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000531
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000536 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000537 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000539
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000540 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000541 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000542 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000543
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000544 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000545 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Daniel Sanders17793142015-02-18 16:24:50 +0000548 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Daniel Sanders17793142015-02-18 16:24:50 +0000552 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000553 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Daniel Sanders17793142015-02-18 16:24:50 +0000556 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Daniel Sanders17793142015-02-18 16:24:50 +0000560 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000568 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000571
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000572 bool hasDSP() const {
573 return getSTI().getFeatureBits()[Mips::FeatureDSP];
574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 bool hasDSPR2() const {
577 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 bool hasDSPR3() const {
581 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 bool hasMSA() const {
585 return getSTI().getFeatureBits()[Mips::FeatureMSA];
586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Kai Nackee0245392015-01-27 19:11:28 +0000588 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000589 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000590 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000591
Daniel Sandersa6994442015-08-18 12:33:54 +0000592 bool inPicMode() {
593 return IsPicEnabled;
594 }
595
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000596 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000597 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000598 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000599
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000600 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000601 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000602 }
603
Eric Christophere8ae3e32015-05-07 23:10:21 +0000604 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000605 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000606 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000607
Toma Tabacud9d344b2015-04-27 14:05:04 +0000608 /// Warn if RegIndex is the same as the current AT.
609 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000610
611 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000612
613 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000614
615 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
616 AsmToken::TokenKind OperatorToken,
617 MCContext &Ctx) override {
618 switch(OperatorToken) {
619 default:
620 llvm_unreachable("Unknown token");
621 return nullptr;
622 case AsmToken::PercentCall16:
623 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
624 case AsmToken::PercentCall_Hi:
625 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
626 case AsmToken::PercentCall_Lo:
627 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
628 case AsmToken::PercentDtprel_Hi:
629 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
630 case AsmToken::PercentDtprel_Lo:
631 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
632 case AsmToken::PercentGot:
633 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
634 case AsmToken::PercentGot_Disp:
635 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
636 case AsmToken::PercentGot_Hi:
637 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
638 case AsmToken::PercentGot_Lo:
639 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
640 case AsmToken::PercentGot_Ofst:
641 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
642 case AsmToken::PercentGot_Page:
643 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
644 case AsmToken::PercentGottprel:
645 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
646 case AsmToken::PercentGp_Rel:
647 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
648 case AsmToken::PercentHi:
649 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
650 case AsmToken::PercentHigher:
651 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
652 case AsmToken::PercentHighest:
653 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
654 case AsmToken::PercentLo:
655 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
656 case AsmToken::PercentNeg:
657 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
658 case AsmToken::PercentPcrel_Hi:
659 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
660 case AsmToken::PercentPcrel_Lo:
661 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
662 case AsmToken::PercentTlsgd:
663 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
664 case AsmToken::PercentTlsldm:
665 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
666 case AsmToken::PercentTprel_Hi:
667 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
668 case AsmToken::PercentTprel_Lo:
669 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
670 }
671 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000672};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000673
674/// MipsOperand - Instances of this class represent a parsed Mips machine
675/// instruction.
676class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000677public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 /// Broad categories of register classes
679 /// The exact class is finalized by the render method.
680 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000681 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000683 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000684 RegKind_FCC = 4, /// FCC
685 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
686 RegKind_MSACtrl = 16, /// MSA control registers
687 RegKind_COP2 = 32, /// COP2
688 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
689 /// context).
690 RegKind_CCR = 128, /// CCR
691 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000692 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000693 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 /// Potentially any (e.g. $1)
695 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
696 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000697 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000698 };
699
700private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000701 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000702 k_Immediate, /// An immediate (possibly involving symbol references)
703 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000704 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000705 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000706 k_RegList, /// A physical register list
707 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000708 } Kind;
709
David Blaikie960ea3f2014-06-08 16:18:35 +0000710public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 MipsOperand(KindTy K, MipsAsmParser &Parser)
712 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
713
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000714 ~MipsOperand() override {
715 switch (Kind) {
716 case k_Immediate:
717 break;
718 case k_Memory:
719 delete Mem.Base;
720 break;
721 case k_RegList:
722 delete RegList.List;
723 case k_RegisterIndex:
724 case k_Token:
725 case k_RegPair:
726 break;
727 }
728 }
729
David Blaikie960ea3f2014-06-08 16:18:35 +0000730private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 /// For diagnostics, and checking the assembler temporary
732 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000733
Eric Christopher8996c5d2013-03-15 00:42:55 +0000734 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000735 const char *Data;
736 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000737 };
738
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000739 struct RegIdxOp {
740 unsigned Index; /// Index into the register class
741 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000742 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000744 };
745
746 struct ImmOp {
747 const MCExpr *Val;
748 };
749
750 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000752 const MCExpr *Off;
753 };
754
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000755 struct RegListOp {
756 SmallVector<unsigned, 10> *List;
757 };
758
Jack Carterb4dbc172012-09-05 23:34:03 +0000759 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000760 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000761 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000762 struct ImmOp Imm;
763 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000764 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000765 };
766
767 SMLoc StartLoc, EndLoc;
768
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000769 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000770 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
771 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000772 const MCRegisterInfo *RegInfo,
773 SMLoc S, SMLoc E,
774 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000775 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000776 Op->RegIdx.Index = Index;
777 Op->RegIdx.RegInfo = RegInfo;
778 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000779 Op->RegIdx.Tok.Data = Str.data();
780 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 Op->StartLoc = S;
782 Op->EndLoc = E;
783 return Op;
784 }
785
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000786public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 /// Coerce the register to GPR32 and return the real register for the current
788 /// target.
789 unsigned getGPR32Reg() const {
790 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000791 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 unsigned ClassID = Mips::GPR32RegClassID;
793 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000794 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000795
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000796 /// Coerce the register to GPR32 and return the real register for the current
797 /// target.
798 unsigned getGPRMM16Reg() const {
799 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
800 unsigned ClassID = Mips::GPR32RegClassID;
801 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
802 }
803
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 /// Coerce the register to GPR64 and return the real register for the current
805 /// target.
806 unsigned getGPR64Reg() const {
807 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
808 unsigned ClassID = Mips::GPR64RegClassID;
809 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000810 }
811
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812private:
813 /// Coerce the register to AFGR64 and return the real register for the current
814 /// target.
815 unsigned getAFGR64Reg() const {
816 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
817 if (RegIdx.Index % 2 != 0)
818 AsmParser.Warning(StartLoc, "Float register should be even.");
819 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
820 .getRegister(RegIdx.Index / 2);
821 }
822
823 /// Coerce the register to FGR64 and return the real register for the current
824 /// target.
825 unsigned getFGR64Reg() const {
826 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
827 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
828 .getRegister(RegIdx.Index);
829 }
830
831 /// Coerce the register to FGR32 and return the real register for the current
832 /// target.
833 unsigned getFGR32Reg() const {
834 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
835 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
836 .getRegister(RegIdx.Index);
837 }
838
839 /// Coerce the register to FGRH32 and return the real register for the current
840 /// target.
841 unsigned getFGRH32Reg() const {
842 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
843 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
844 .getRegister(RegIdx.Index);
845 }
846
847 /// Coerce the register to FCC and return the real register for the current
848 /// target.
849 unsigned getFCCReg() const {
850 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
851 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
852 .getRegister(RegIdx.Index);
853 }
854
855 /// Coerce the register to MSA128 and return the real register for the current
856 /// target.
857 unsigned getMSA128Reg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
859 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
860 // identical
861 unsigned ClassID = Mips::MSA128BRegClassID;
862 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
863 }
864
865 /// Coerce the register to MSACtrl and return the real register for the
866 /// current target.
867 unsigned getMSACtrlReg() const {
868 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
869 unsigned ClassID = Mips::MSACtrlRegClassID;
870 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
871 }
872
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000873 /// Coerce the register to COP0 and return the real register for the
874 /// current target.
875 unsigned getCOP0Reg() const {
876 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
877 unsigned ClassID = Mips::COP0RegClassID;
878 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
879 }
880
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000881 /// Coerce the register to COP2 and return the real register for the
882 /// current target.
883 unsigned getCOP2Reg() const {
884 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
885 unsigned ClassID = Mips::COP2RegClassID;
886 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
887 }
888
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000889 /// Coerce the register to COP3 and return the real register for the
890 /// current target.
891 unsigned getCOP3Reg() const {
892 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
893 unsigned ClassID = Mips::COP3RegClassID;
894 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
895 }
896
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 /// Coerce the register to ACC64DSP and return the real register for the
898 /// current target.
899 unsigned getACC64DSPReg() const {
900 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
901 unsigned ClassID = Mips::ACC64DSPRegClassID;
902 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
903 }
904
905 /// Coerce the register to HI32DSP and return the real register for the
906 /// current target.
907 unsigned getHI32DSPReg() const {
908 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
909 unsigned ClassID = Mips::HI32DSPRegClassID;
910 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
911 }
912
913 /// Coerce the register to LO32DSP and return the real register for the
914 /// current target.
915 unsigned getLO32DSPReg() const {
916 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
917 unsigned ClassID = Mips::LO32DSPRegClassID;
918 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
919 }
920
921 /// Coerce the register to CCR and return the real register for the
922 /// current target.
923 unsigned getCCRReg() const {
924 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
925 unsigned ClassID = Mips::CCRRegClassID;
926 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
927 }
928
929 /// Coerce the register to HWRegs and return the real register for the
930 /// current target.
931 unsigned getHWRegsReg() const {
932 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
933 unsigned ClassID = Mips::HWRegsRegClassID;
934 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
935 }
936
937public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000938 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000939 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000940 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000941 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000942 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000943 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000944 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000945 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000946 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000947
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 void addRegOperands(MCInst &Inst, unsigned N) const {
949 llvm_unreachable("Use a custom parser instead");
950 }
951
Daniel Sanders21bce302014-04-01 12:35:23 +0000952 /// Render the operand to an MCInst as a GPR32
953 /// Asserts if the wrong number of operands are requested, or the operand
954 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000955 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
956 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000957 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000958 }
959
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000960 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
961 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000962 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000963 }
964
Jozef Kolek1904fa22014-11-24 14:25:53 +0000965 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
966 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000967 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000968 }
969
Zoran Jovanovic41688672015-02-10 16:36:20 +0000970 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
971 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000972 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000973 }
974
Daniel Sanders21bce302014-04-01 12:35:23 +0000975 /// Render the operand to an MCInst as a GPR64
976 /// Asserts if the wrong number of operands are requested, or the operand
977 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000978 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
979 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000980 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000981 }
982
983 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
984 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000985 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 }
987
988 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000990 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 }
992
993 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000996 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +0000997 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000998 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +0000999 AsmParser.getParser().printError(
1000 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1001 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 }
1003
1004 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001006 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001007 }
1008
1009 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001011 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 }
1013
1014 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001016 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 }
1018
1019 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001021 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 }
1023
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001024 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
1026 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1027 }
1028
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001031 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 }
1033
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001034 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1035 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001036 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001037 }
1038
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001039 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1040 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001041 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 }
1043
1044 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1045 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001046 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001047 }
1048
1049 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1050 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001051 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 }
1053
1054 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1055 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001056 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 }
1058
1059 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1060 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001061 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 }
1063
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001064 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001065 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001067 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001068 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001069 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001070 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001071 Inst.addOperand(MCOperand::createImm(Imm));
1072 }
1073
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001074 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001075 void addSImmOperands(MCInst &Inst, unsigned N) const {
1076 if (isImm() && !isConstantImm()) {
1077 addExpr(Inst, getImm());
1078 return;
1079 }
1080 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1081 }
1082
1083 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001084 void addUImmOperands(MCInst &Inst, unsigned N) const {
1085 if (isImm() && !isConstantImm()) {
1086 addExpr(Inst, getImm());
1087 return;
1088 }
1089 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1090 }
1091
Daniel Sanders78e89022016-03-11 11:37:50 +00001092 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1093 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
1095 int64_t Imm = getConstantImm() - Offset;
1096 Imm = SignExtend64<Bits>(Imm);
1097 Imm += Offset;
1098 Imm += AdjustOffset;
1099 Inst.addOperand(MCOperand::createImm(Imm));
1100 }
1101
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001102 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001103 assert(N == 1 && "Invalid number of operands!");
1104 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001105 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001106 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001107
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001108 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001109 assert(N == 2 && "Invalid number of operands!");
1110
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001111 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1112 ? getMemBase()->getGPR64Reg()
1113 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001114
1115 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001117 }
1118
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001119 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1120 assert(N == 2 && "Invalid number of operands!");
1121
Jim Grosbache9119e42015-05-13 18:37:00 +00001122 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001123
1124 const MCExpr *Expr = getMemOff();
1125 addExpr(Inst, Expr);
1126 }
1127
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001128 void addRegListOperands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
1130
1131 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001132 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001133 }
1134
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001135 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1136 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001137 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001138 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001139 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1140 Inst.addOperand(MCOperand::createReg(
1141 RegIdx.RegInfo->getRegClass(
1142 AsmParser.getABI().AreGprs64bit()
1143 ? Mips::GPR64RegClassID
1144 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1145 Inst.addOperand(MCOperand::createReg(
1146 RegIdx.RegInfo->getRegClass(
1147 AsmParser.getABI().AreGprs64bit()
1148 ? Mips::GPR64RegClassID
1149 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001150 }
1151
Zoran Jovanovic41688672015-02-10 16:36:20 +00001152 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1153 assert(N == 2 && "Invalid number of operands!");
1154 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001155 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001156 }
1157
Craig Topper56c590a2014-04-29 07:58:02 +00001158 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001159 // As a special case until we sort out the definition of div/divu, accept
1160 // $0/$zero here so that MCK_ZERO works correctly.
1161 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001163
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001164 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001165 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001166
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001168 int64_t Res;
1169 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001170 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001171
Daniel Sanders52da7af2015-11-06 12:11:03 +00001172 bool isConstantImmz() const {
1173 return isConstantImm() && getConstantImm() == 0;
1174 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001175
Daniel Sandersea4f6532015-11-06 12:22:31 +00001176 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1177 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1178 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001179
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001180 template <unsigned Bits> bool isSImm() const {
1181 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1182 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001183
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001184 template <unsigned Bits> bool isUImm() const {
1185 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1186 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001187
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001188 template <unsigned Bits> bool isAnyImm() const {
1189 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1190 isUInt<Bits>(getConstantImm()))
1191 : isImm();
1192 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001193
Daniel Sanders78e89022016-03-11 11:37:50 +00001194 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1195 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001196 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001197
Hrvoje Varga46458d02016-02-25 12:53:29 +00001198 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1199 return isConstantImm() && getConstantImm() >= Bottom &&
1200 getConstantImm() <= Top;
1201 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001202
Craig Topper56c590a2014-04-29 07:58:02 +00001203 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001204 // Note: It's not possible to pretend that other operand kinds are tokens.
1205 // The matcher emitter checks tokens first.
1206 return Kind == k_Token;
1207 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001208
Craig Topper56c590a2014-04-29 07:58:02 +00001209 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001210
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001211 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001212 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001213 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001214
Simon Dardis4ccda502016-05-27 13:56:36 +00001215 // Allow relocation operators.
1216 // FIXME: This predicate and others need to look through binary expressions
1217 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001218 template <unsigned Bits, unsigned ShiftAmount = 0>
1219 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001220 if (!isMem())
1221 return false;
1222 if (!getMemBase()->isGPRAsmReg())
1223 return false;
1224 if (isa<MCTargetExpr>(getMemOff()) ||
1225 (isConstantMemOff() &&
1226 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1227 return true;
1228 MCValue Res;
1229 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1230 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001231 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001232
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001233 bool isMemWithGRPMM16Base() const {
1234 return isMem() && getMemBase()->isMM16AsmReg();
1235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001237 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1238 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1239 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1240 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001241
Jozef Kolek12c69822014-12-23 16:16:33 +00001242 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1243 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1244 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1245 && (getMemBase()->getGPR32Reg() == Mips::SP);
1246 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001247
Daniel Sanderse473dc92016-05-09 13:38:25 +00001248 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1249 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1250 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1251 && (getMemBase()->getGPR32Reg() == Mips::GP);
1252 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001253
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001254 template <unsigned Bits, unsigned ShiftLeftAmount>
1255 bool isScaledUImm() const {
1256 return isConstantImm() &&
1257 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001258 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001259
Daniel Sanders97297772016-03-22 14:40:00 +00001260 template <unsigned Bits, unsigned ShiftLeftAmount>
1261 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001262 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1263 return true;
1264 // Operand can also be a symbol or symbol plus offset in case of relocations.
1265 if (Kind != k_Immediate)
1266 return false;
1267 MCValue Res;
1268 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1269 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001270 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001271
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001272 bool isRegList16() const {
1273 if (!isRegList())
1274 return false;
1275
1276 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001277 if (Size < 2 || Size > 5)
1278 return false;
1279
1280 unsigned R0 = RegList.List->front();
1281 unsigned R1 = RegList.List->back();
1282 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1283 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001284 return false;
1285
1286 int PrevReg = *RegList.List->begin();
1287 for (int i = 1; i < Size - 1; i++) {
1288 int Reg = (*(RegList.List))[i];
1289 if ( Reg != PrevReg + 1)
1290 return false;
1291 PrevReg = Reg;
1292 }
1293
1294 return true;
1295 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001296
Vladimir Medic2b953d02013-10-01 09:48:56 +00001297 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001298
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001299 bool isLSAImm() const {
1300 if (!isConstantImm())
1301 return false;
1302 int64_t Val = getConstantImm();
1303 return 1 <= Val && Val <= 4;
1304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001306 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001307
Zoran Jovanovic41688672015-02-10 16:36:20 +00001308 bool isMovePRegPair() const {
1309 if (Kind != k_RegList || RegList.List->size() != 2)
1310 return false;
1311
1312 unsigned R0 = RegList.List->front();
1313 unsigned R1 = RegList.List->back();
1314
1315 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1316 (R0 == Mips::A1 && R1 == Mips::A3) ||
1317 (R0 == Mips::A2 && R1 == Mips::A3) ||
1318 (R0 == Mips::A0 && R1 == Mips::S5) ||
1319 (R0 == Mips::A0 && R1 == Mips::S6) ||
1320 (R0 == Mips::A0 && R1 == Mips::A1) ||
1321 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001322 (R0 == Mips::A0 && R1 == Mips::A3) ||
1323 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1324 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1325 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1326 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1327 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1328 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1329 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1330 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001331 return true;
1332
1333 return false;
1334 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001335
1336 StringRef getToken() const {
1337 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001338 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001339 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001340
Zlatko Buljanba553a62016-05-09 08:07:28 +00001341 bool isRegPair() const {
1342 return Kind == k_RegPair && RegIdx.Index <= 30;
1343 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001344
Craig Topper56c590a2014-04-29 07:58:02 +00001345 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001346 // As a special case until we sort out the definition of div/divu, accept
1347 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001348 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1349 RegIdx.Kind & RegKind_GPR)
1350 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001351
Daniel Sanders976d9382016-07-05 13:38:40 +00001352 llvm_unreachable("Invalid access!");
1353 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001354 }
1355
Jack Carterb4dbc172012-09-05 23:34:03 +00001356 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001357 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001358 return Imm.Val;
1359 }
1360
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 int64_t getConstantImm() const {
1362 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001363 int64_t Value = 0;
1364 (void)Val->evaluateAsAbsolute(Value);
1365 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001366 }
1367
1368 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001369 assert((Kind == k_Memory) && "Invalid access!");
1370 return Mem.Base;
1371 }
1372
1373 const MCExpr *getMemOff() const {
1374 assert((Kind == k_Memory) && "Invalid access!");
1375 return Mem.Off;
1376 }
1377
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001378 int64_t getConstantMemOff() const {
1379 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1380 }
1381
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001382 const SmallVectorImpl<unsigned> &getRegList() const {
1383 assert((Kind == k_RegList) && "Invalid access!");
1384 return *(RegList.List);
1385 }
1386
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001387 unsigned getRegPair() const {
1388 assert((Kind == k_RegPair) && "Invalid access!");
1389 return RegIdx.Index;
1390 }
1391
David Blaikie960ea3f2014-06-08 16:18:35 +00001392 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1393 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001394 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001395 Op->Tok.Data = Str.data();
1396 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001397 Op->StartLoc = S;
1398 Op->EndLoc = S;
1399 return Op;
1400 }
1401
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001402 /// Create a numeric register (e.g. $1). The exact register remains
1403 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001404 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001405 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1406 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001407 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001408 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001409 }
1410
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001411 /// Create a register that is definitely a GPR.
1412 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001413 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001414 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1415 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1416 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001417 }
1418
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 /// Create a register that is definitely a FGR.
1420 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001421 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001422 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1423 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1424 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001425 }
1426
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001427 /// Create a register that is definitely a HWReg.
1428 /// This is typically only used for named registers such as $hwr_cpunum.
1429 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001430 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001431 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001432 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001433 }
1434
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001435 /// Create a register that is definitely an FCC.
1436 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001437 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001438 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1439 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1440 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001441 }
1442
1443 /// Create a register that is definitely an ACC.
1444 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001445 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001446 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1447 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1448 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001449 }
1450
1451 /// Create a register that is definitely an MSA128.
1452 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001453 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001454 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1455 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1456 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001457 }
1458
1459 /// Create a register that is definitely an MSACtrl.
1460 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001461 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001462 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1463 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1464 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001465 }
1466
David Blaikie960ea3f2014-06-08 16:18:35 +00001467 static std::unique_ptr<MipsOperand>
1468 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001469 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001470 Op->Imm.Val = Val;
1471 Op->StartLoc = S;
1472 Op->EndLoc = E;
1473 return Op;
1474 }
1475
David Blaikie960ea3f2014-06-08 16:18:35 +00001476 static std::unique_ptr<MipsOperand>
1477 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1478 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001479 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001480 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001481 Op->Mem.Off = Off;
1482 Op->StartLoc = S;
1483 Op->EndLoc = E;
1484 return Op;
1485 }
1486
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001487 static std::unique_ptr<MipsOperand>
1488 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1489 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001490 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001491
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001492 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001493 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001494 Op->StartLoc = StartLoc;
1495 Op->EndLoc = EndLoc;
1496 return Op;
1497 }
1498
Daniel Sandersd044e492016-05-09 13:10:57 +00001499 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1500 SMLoc S, SMLoc E,
1501 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001502 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001503 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001504 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1505 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001506 Op->StartLoc = S;
1507 Op->EndLoc = E;
1508 return Op;
1509 }
1510
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001511 bool isGPRAsmReg() const {
1512 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001513 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001514
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001515 bool isMM16AsmReg() const {
1516 if (!(isRegIdx() && RegIdx.Kind))
1517 return false;
1518 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1519 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001520
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001521 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001522 bool isMM16AsmRegZero() const {
1523 if (!(isRegIdx() && RegIdx.Kind))
1524 return false;
1525 return (RegIdx.Index == 0 ||
1526 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1527 RegIdx.Index == 17);
1528 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001529
Zoran Jovanovic41688672015-02-10 16:36:20 +00001530 bool isMM16AsmRegMoveP() const {
1531 if (!(isRegIdx() && RegIdx.Kind))
1532 return false;
1533 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1534 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1535 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001536
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001537 bool isFGRAsmReg() const {
1538 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1539 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001540 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001541
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001542 bool isHWRegsAsmReg() const {
1543 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001544 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001545
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001546 bool isCCRAsmReg() const {
1547 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001548 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001549
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001550 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001551 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1552 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001553 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001555
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001556 bool isACCAsmReg() const {
1557 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001559
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001560 bool isCOP0AsmReg() const {
1561 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001563
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001564 bool isCOP2AsmReg() const {
1565 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001567
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001568 bool isCOP3AsmReg() const {
1569 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001571
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001572 bool isMSA128AsmReg() const {
1573 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001575
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001576 bool isMSACtrlAsmReg() const {
1577 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001578 }
1579
Jack Carterb4dbc172012-09-05 23:34:03 +00001580 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001581 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001582 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001583 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001584
Craig Topper56c590a2014-04-29 07:58:02 +00001585 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001586 switch (Kind) {
1587 case k_Immediate:
1588 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001589 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001590 OS << ">";
1591 break;
1592 case k_Memory:
1593 OS << "Mem<";
1594 Mem.Base->print(OS);
1595 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001596 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001597 OS << ">";
1598 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001599 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001600 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1601 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001602 break;
1603 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001604 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001605 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001606 case k_RegList:
1607 OS << "RegList< ";
1608 for (auto Reg : (*RegList.List))
1609 OS << Reg << " ";
1610 OS << ">";
1611 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001612 case k_RegPair:
1613 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1614 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001615 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001616 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001617
1618 bool isValidForTie(const MipsOperand &Other) const {
1619 if (Kind != Other.Kind)
1620 return false;
1621
1622 switch (Kind) {
1623 default:
1624 llvm_unreachable("Unexpected kind");
1625 return false;
1626 case k_RegisterIndex: {
1627 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1628 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1629 return Token == OtherToken;
1630 }
1631 }
1632 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001633}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001634
1635} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001636
Jack Carter9e65aa32013-03-22 00:05:30 +00001637namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001638
Jack Carter9e65aa32013-03-22 00:05:30 +00001639extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001640
1641} // end namespace llvm
1642
Jack Carter9e65aa32013-03-22 00:05:30 +00001643static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1644 return MipsInsts[Opcode];
1645}
1646
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001647static bool hasShortDelaySlot(unsigned Opcode) {
1648 switch (Opcode) {
1649 case Mips::JALS_MM:
1650 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001651 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001652 case Mips::BGEZALS_MM:
1653 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001654 return true;
1655 default:
1656 return false;
1657 }
1658}
1659
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001660static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1661 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1662 return &SRExpr->getSymbol();
1663 }
1664
1665 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1666 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1667 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1668
1669 if (LHSSym)
1670 return LHSSym;
1671
1672 if (RHSSym)
1673 return RHSSym;
1674
1675 return nullptr;
1676 }
1677
1678 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1679 return getSingleMCSymbol(UExpr->getSubExpr());
1680
1681 return nullptr;
1682}
1683
1684static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1685 if (isa<MCSymbolRefExpr>(Expr))
1686 return 1;
1687
1688 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1689 return countMCSymbolRefExpr(BExpr->getLHS()) +
1690 countMCSymbolRefExpr(BExpr->getRHS());
1691
1692 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1693 return countMCSymbolRefExpr(UExpr->getSubExpr());
1694
1695 return 0;
1696}
1697
Jack Carter9e65aa32013-03-22 00:05:30 +00001698bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001699 MCStreamer &Out,
1700 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001701 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001702 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001703 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001704
Jack Carter9e65aa32013-03-22 00:05:30 +00001705 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001706
1707 if (MCID.isBranch() || MCID.isCall()) {
1708 const unsigned Opcode = Inst.getOpcode();
1709 MCOperand Offset;
1710
1711 switch (Opcode) {
1712 default:
1713 break;
Kai Nackee0245392015-01-27 19:11:28 +00001714 case Mips::BBIT0:
1715 case Mips::BBIT032:
1716 case Mips::BBIT1:
1717 case Mips::BBIT132:
1718 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001719 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001720
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001721 case Mips::BEQ:
1722 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001723 case Mips::BEQ_MM:
1724 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001725 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001726 Offset = Inst.getOperand(2);
1727 if (!Offset.isImm())
1728 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001729 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001730 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001731 if (OffsetToAlignment(Offset.getImm(),
1732 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001733 return Error(IDLoc, "branch to misaligned address");
1734 break;
1735 case Mips::BGEZ:
1736 case Mips::BGTZ:
1737 case Mips::BLEZ:
1738 case Mips::BLTZ:
1739 case Mips::BGEZAL:
1740 case Mips::BLTZAL:
1741 case Mips::BC1F:
1742 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001743 case Mips::BGEZ_MM:
1744 case Mips::BGTZ_MM:
1745 case Mips::BLEZ_MM:
1746 case Mips::BLTZ_MM:
1747 case Mips::BGEZAL_MM:
1748 case Mips::BLTZAL_MM:
1749 case Mips::BC1F_MM:
1750 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001751 case Mips::BC1EQZC_MMR6:
1752 case Mips::BC1NEZC_MMR6:
1753 case Mips::BC2EQZC_MMR6:
1754 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001755 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001756 Offset = Inst.getOperand(1);
1757 if (!Offset.isImm())
1758 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001759 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001760 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001761 if (OffsetToAlignment(Offset.getImm(),
1762 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001763 return Error(IDLoc, "branch to misaligned address");
1764 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001765 case Mips::BGEC: case Mips::BGEC_MMR6:
1766 case Mips::BLTC: case Mips::BLTC_MMR6:
1767 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1768 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1769 case Mips::BEQC: case Mips::BEQC_MMR6:
1770 case Mips::BNEC: case Mips::BNEC_MMR6:
1771 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1772 Offset = Inst.getOperand(2);
1773 if (!Offset.isImm())
1774 break; // We'll deal with this situation later on when applying fixups.
1775 if (!isIntN(18, Offset.getImm()))
1776 return Error(IDLoc, "branch target out of range");
1777 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1778 return Error(IDLoc, "branch to misaligned address");
1779 break;
1780 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1781 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1782 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1783 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1784 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1785 Offset = Inst.getOperand(1);
1786 if (!Offset.isImm())
1787 break; // We'll deal with this situation later on when applying fixups.
1788 if (!isIntN(18, Offset.getImm()))
1789 return Error(IDLoc, "branch target out of range");
1790 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1791 return Error(IDLoc, "branch to misaligned address");
1792 break;
1793 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1794 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1795 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1796 Offset = Inst.getOperand(1);
1797 if (!Offset.isImm())
1798 break; // We'll deal with this situation later on when applying fixups.
1799 if (!isIntN(23, Offset.getImm()))
1800 return Error(IDLoc, "branch target out of range");
1801 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1802 return Error(IDLoc, "branch to misaligned address");
1803 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001804 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001805 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001806 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001807 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001808 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1809 Offset = Inst.getOperand(1);
1810 if (!Offset.isImm())
1811 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001812 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001813 return Error(IDLoc, "branch target out of range");
1814 if (OffsetToAlignment(Offset.getImm(), 2LL))
1815 return Error(IDLoc, "branch to misaligned address");
1816 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001817 }
1818 }
1819
Daniel Sandersa84989a2014-06-16 13:25:35 +00001820 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1821 // We still accept it but it is a normal nop.
1822 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1823 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1824 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1825 "nop instruction");
1826 }
1827
Kai Nackee0245392015-01-27 19:11:28 +00001828 if (hasCnMips()) {
1829 const unsigned Opcode = Inst.getOpcode();
1830 MCOperand Opnd;
1831 int Imm;
1832
1833 switch (Opcode) {
1834 default:
1835 break;
1836
1837 case Mips::BBIT0:
1838 case Mips::BBIT032:
1839 case Mips::BBIT1:
1840 case Mips::BBIT132:
1841 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1842 // The offset is handled above
1843 Opnd = Inst.getOperand(1);
1844 if (!Opnd.isImm())
1845 return Error(IDLoc, "expected immediate operand kind");
1846 Imm = Opnd.getImm();
1847 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1848 Opcode == Mips::BBIT1 ? 63 : 31))
1849 return Error(IDLoc, "immediate operand value out of range");
1850 if (Imm > 31) {
1851 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1852 : Mips::BBIT132);
1853 Inst.getOperand(1).setImm(Imm - 32);
1854 }
1855 break;
1856
Kai Nackee0245392015-01-27 19:11:28 +00001857 case Mips::SEQi:
1858 case Mips::SNEi:
1859 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1860 Opnd = Inst.getOperand(2);
1861 if (!Opnd.isImm())
1862 return Error(IDLoc, "expected immediate operand kind");
1863 Imm = Opnd.getImm();
1864 if (!isInt<10>(Imm))
1865 return Error(IDLoc, "immediate operand value out of range");
1866 break;
1867 }
1868 }
1869
Simon Atanasyan50485142016-12-12 17:40:26 +00001870 // For PIC code convert unconditional jump to unconditional branch.
1871 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1872 inPicMode()) {
1873 MCInst BInst;
1874 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1875 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1876 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1877 BInst.addOperand(Inst.getOperand(0));
1878 Inst = BInst;
1879 }
1880
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001881 // This expansion is not in a function called by tryExpandInstruction()
1882 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001883 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1884 inPicMode()) {
1885 warnIfNoMacro(IDLoc);
1886
1887 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1888
1889 // We can do this expansion if there's only 1 symbol in the argument
1890 // expression.
1891 if (countMCSymbolRefExpr(JalExpr) > 1)
1892 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1893
1894 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001895 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001896 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1897
1898 // FIXME: Add support for label+offset operands (currently causes an error).
1899 // FIXME: Add support for forward-declared local symbols.
1900 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00001901 if (JalSym->isInSection() || JalSym->isTemporary() ||
1902 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001903 if (isABI_O32()) {
1904 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001905 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001906 // R_(MICRO)MIPS_GOT16 label
1907 // addiu $25, $25, 0
1908 // R_(MICRO)MIPS_LO16 label
1909 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001910 const MCExpr *Got16RelocExpr =
1911 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1912 const MCExpr *Lo16RelocExpr =
1913 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001914
Daniel Sandersa736b372016-04-29 13:33:12 +00001915 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1916 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1917 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1918 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001919 } else if (isABI_N32() || isABI_N64()) {
1920 // If it's a local symbol and the N32/N64 ABIs are being used,
1921 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001922 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001923 // R_(MICRO)MIPS_GOT_DISP label
1924 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001925 const MCExpr *GotDispRelocExpr =
1926 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001927
Daniel Sandersa736b372016-04-29 13:33:12 +00001928 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1929 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1930 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001931 }
1932 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001933 // If it's an external/weak symbol, we expand to:
1934 // lw/ld $25, 0($gp)
1935 // R_(MICRO)MIPS_CALL16 label
1936 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001937 const MCExpr *Call16RelocExpr =
1938 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001939
Daniel Sandersa736b372016-04-29 13:33:12 +00001940 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1941 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001942 }
1943
1944 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001945 if (IsCpRestoreSet && inMicroMipsMode())
1946 JalrInst.setOpcode(Mips::JALRS_MM);
1947 else
1948 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001949 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1950 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1951
1952 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1953 // This relocation is supposed to be an optimization hint for the linker
1954 // and is not necessary for correctness.
1955
1956 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001957 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001958 }
1959
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001960 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1961 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001962 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001963 // reference or immediate we may have to expand instructions.
1964 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001965 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001966 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1967 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001968 MCOperand &Op = Inst.getOperand(i);
1969 if (Op.isImm()) {
1970 int MemOffset = Op.getImm();
1971 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001972 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001973 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001974 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001975 }
1976 } else if (Op.isExpr()) {
1977 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001978 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001979 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001980 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001981 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001982 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001983 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001984 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001985 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001986 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001987 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001988 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001989 }
1990 }
1991 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001992 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001993 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001994
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001995 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001996 if (MCID.mayLoad()) {
1997 // Try to create 16-bit GP relative load instruction.
1998 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1999 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2000 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2001 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2002 MCOperand &Op = Inst.getOperand(i);
2003 if (Op.isImm()) {
2004 int MemOffset = Op.getImm();
2005 MCOperand &DstReg = Inst.getOperand(0);
2006 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002007 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002008 getContext().getRegisterInfo()->getRegClass(
2009 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002010 (BaseReg.getReg() == Mips::GP ||
2011 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002012
Daniel Sandersa736b372016-04-29 13:33:12 +00002013 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2014 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002015 return false;
2016 }
2017 }
2018 }
2019 } // for
2020 } // if load
2021
2022 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2023
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002024 MCOperand Opnd;
2025 int Imm;
2026
2027 switch (Inst.getOpcode()) {
2028 default:
2029 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002030 case Mips::ADDIUSP_MM:
2031 Opnd = Inst.getOperand(0);
2032 if (!Opnd.isImm())
2033 return Error(IDLoc, "expected immediate operand kind");
2034 Imm = Opnd.getImm();
2035 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2036 Imm % 4 != 0)
2037 return Error(IDLoc, "immediate operand value out of range");
2038 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002039 case Mips::SLL16_MM:
2040 case Mips::SRL16_MM:
2041 Opnd = Inst.getOperand(2);
2042 if (!Opnd.isImm())
2043 return Error(IDLoc, "expected immediate operand kind");
2044 Imm = Opnd.getImm();
2045 if (Imm < 1 || Imm > 8)
2046 return Error(IDLoc, "immediate operand value out of range");
2047 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002048 case Mips::LI16_MM:
2049 Opnd = Inst.getOperand(1);
2050 if (!Opnd.isImm())
2051 return Error(IDLoc, "expected immediate operand kind");
2052 Imm = Opnd.getImm();
2053 if (Imm < -1 || Imm > 126)
2054 return Error(IDLoc, "immediate operand value out of range");
2055 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002056 case Mips::ADDIUR2_MM:
2057 Opnd = Inst.getOperand(2);
2058 if (!Opnd.isImm())
2059 return Error(IDLoc, "expected immediate operand kind");
2060 Imm = Opnd.getImm();
2061 if (!(Imm == 1 || Imm == -1 ||
2062 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2063 return Error(IDLoc, "immediate operand value out of range");
2064 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002065 case Mips::ANDI16_MM:
2066 Opnd = Inst.getOperand(2);
2067 if (!Opnd.isImm())
2068 return Error(IDLoc, "expected immediate operand kind");
2069 Imm = Opnd.getImm();
2070 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2071 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2072 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2073 return Error(IDLoc, "immediate operand value out of range");
2074 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002075 case Mips::LBU16_MM:
2076 Opnd = Inst.getOperand(2);
2077 if (!Opnd.isImm())
2078 return Error(IDLoc, "expected immediate operand kind");
2079 Imm = Opnd.getImm();
2080 if (Imm < -1 || Imm > 14)
2081 return Error(IDLoc, "immediate operand value out of range");
2082 break;
2083 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002084 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002085 Opnd = Inst.getOperand(2);
2086 if (!Opnd.isImm())
2087 return Error(IDLoc, "expected immediate operand kind");
2088 Imm = Opnd.getImm();
2089 if (Imm < 0 || Imm > 15)
2090 return Error(IDLoc, "immediate operand value out of range");
2091 break;
2092 case Mips::LHU16_MM:
2093 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002094 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002095 Opnd = Inst.getOperand(2);
2096 if (!Opnd.isImm())
2097 return Error(IDLoc, "expected immediate operand kind");
2098 Imm = Opnd.getImm();
2099 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2100 return Error(IDLoc, "immediate operand value out of range");
2101 break;
2102 case Mips::LW16_MM:
2103 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002104 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002105 Opnd = Inst.getOperand(2);
2106 if (!Opnd.isImm())
2107 return Error(IDLoc, "expected immediate operand kind");
2108 Imm = Opnd.getImm();
2109 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2110 return Error(IDLoc, "immediate operand value out of range");
2111 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002112 case Mips::ADDIUPC_MM:
2113 MCOperand Opnd = Inst.getOperand(1);
2114 if (!Opnd.isImm())
2115 return Error(IDLoc, "expected immediate operand kind");
2116 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002117 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002118 return Error(IDLoc, "immediate operand value out of range");
2119 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002120 }
2121 }
2122
Daniel Sandersd8c07762016-04-18 12:35:36 +00002123 bool FillDelaySlot =
2124 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2125 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002126 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002127
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002128 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002129 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002130 switch (ExpandResult) {
2131 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002132 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002133 break;
2134 case MER_Success:
2135 break;
2136 case MER_Fail:
2137 return true;
2138 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002139
Daniel Sanderscda908a2016-05-16 09:10:13 +00002140 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2141 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2142 if (inMicroMipsMode())
2143 TOut.setUsesMicroMips();
2144
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002145 // If this instruction has a delay slot and .set reorder is active,
2146 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002147 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002148 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2149 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002150 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002151
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002152 if ((Inst.getOpcode() == Mips::JalOneReg ||
2153 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2154 isPicAndNotNxxAbi()) {
2155 if (IsCpRestoreSet) {
2156 // We need a NOP between the JALR and the LW:
2157 // If .set reorder has been used, we've already emitted a NOP.
2158 // If .set noreorder has been used, we need to emit a NOP at this point.
2159 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002160 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2161 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002162
2163 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002164 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002165 } else
2166 Warning(IDLoc, "no .cprestore used in PIC mode");
2167 }
2168
Jack Carter9e65aa32013-03-22 00:05:30 +00002169 return false;
2170}
2171
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002172MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002173MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2174 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002175 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002177 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002178 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002179 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002180 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002181 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002182 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002183 case Mips::LoadAddrImm64:
2184 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2185 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2186 "expected immediate operand kind");
2187
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002188 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2189 Inst.getOperand(1),
2190 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002191 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002192 ? MER_Fail
2193 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002194 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002195 case Mips::LoadAddrReg64:
2196 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2197 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2198 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2199 "expected immediate operand kind");
2200
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002201 return expandLoadAddress(Inst.getOperand(0).getReg(),
2202 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2203 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002204 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002205 ? MER_Fail
2206 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002207 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002208 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002209 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2210 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002211 case Mips::SWM_MM:
2212 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002213 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2214 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002215 case Mips::JalOneReg:
2216 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002217 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002218 case Mips::BneImm:
2219 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002220 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002221 case Mips::BLT:
2222 case Mips::BLE:
2223 case Mips::BGE:
2224 case Mips::BGT:
2225 case Mips::BLTU:
2226 case Mips::BLEU:
2227 case Mips::BGEU:
2228 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002229 case Mips::BLTL:
2230 case Mips::BLEL:
2231 case Mips::BGEL:
2232 case Mips::BGTL:
2233 case Mips::BLTUL:
2234 case Mips::BLEUL:
2235 case Mips::BGEUL:
2236 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002237 case Mips::BLTImmMacro:
2238 case Mips::BLEImmMacro:
2239 case Mips::BGEImmMacro:
2240 case Mips::BGTImmMacro:
2241 case Mips::BLTUImmMacro:
2242 case Mips::BLEUImmMacro:
2243 case Mips::BGEUImmMacro:
2244 case Mips::BGTUImmMacro:
2245 case Mips::BLTLImmMacro:
2246 case Mips::BLELImmMacro:
2247 case Mips::BGELImmMacro:
2248 case Mips::BGTLImmMacro:
2249 case Mips::BLTULImmMacro:
2250 case Mips::BLEULImmMacro:
2251 case Mips::BGEULImmMacro:
2252 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002253 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002254 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002255 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2256 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002257 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002258 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2259 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002260 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002261 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2262 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002263 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002264 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2265 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002266 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002267 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2268 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002269 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002270 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002271 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002272 case Mips::PseudoTRUNC_W_D:
2273 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2274 : MER_Success;
2275 case Mips::Ulh:
2276 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2277 case Mips::Ulhu:
2278 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002279 case Mips::Ush:
2280 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002281 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002282 case Mips::Usw:
2283 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002284 case Mips::NORImm:
2285 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002286 case Mips::ADDi:
2287 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002288 case Mips::SLTi:
2289 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002290 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2291 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2292 int64_t ImmValue = Inst.getOperand(2).getImm();
2293 if (isInt<16>(ImmValue))
2294 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002295 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2296 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002297 }
2298 return MER_NotAMacro;
2299 case Mips::ANDi:
2300 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002301 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002302 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2303 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2304 int64_t ImmValue = Inst.getOperand(2).getImm();
2305 if (isUInt<16>(ImmValue))
2306 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002307 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2308 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002309 }
2310 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002311 case Mips::ROL:
2312 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002313 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002314 case Mips::ROLImm:
2315 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002316 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002317 case Mips::DROL:
2318 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002319 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002320 case Mips::DROLImm:
2321 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002322 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002323 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002324 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002325 case Mips::LDMacro:
2326 case Mips::SDMacro:
2327 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2328 Inst.getOpcode() == Mips::LDMacro)
2329 ? MER_Fail
2330 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002331 case Mips::SEQMacro:
2332 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2333 case Mips::SEQIMacro:
2334 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002335 }
Jack Carter30a59822012-10-04 04:03:53 +00002336}
Jack Carter92995f12012-10-06 00:53:28 +00002337
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002338bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002339 MCStreamer &Out,
2340 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002341 MipsTargetStreamer &TOut = getTargetStreamer();
2342
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002343 // Create a JALR instruction which is going to replace the pseudo-JAL.
2344 MCInst JalrInst;
2345 JalrInst.setLoc(IDLoc);
2346 const MCOperand FirstRegOp = Inst.getOperand(0);
2347 const unsigned Opcode = Inst.getOpcode();
2348
2349 if (Opcode == Mips::JalOneReg) {
2350 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002351 if (IsCpRestoreSet && inMicroMipsMode()) {
2352 JalrInst.setOpcode(Mips::JALRS16_MM);
2353 JalrInst.addOperand(FirstRegOp);
2354 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002355 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002356 JalrInst.addOperand(FirstRegOp);
2357 } else {
2358 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002359 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002360 JalrInst.addOperand(FirstRegOp);
2361 }
2362 } else if (Opcode == Mips::JalTwoReg) {
2363 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002364 if (IsCpRestoreSet && inMicroMipsMode())
2365 JalrInst.setOpcode(Mips::JALRS_MM);
2366 else
2367 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002368 JalrInst.addOperand(FirstRegOp);
2369 const MCOperand SecondRegOp = Inst.getOperand(1);
2370 JalrInst.addOperand(SecondRegOp);
2371 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002372 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002373
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002374 // If .set reorder is active and branch instruction has a delay slot,
2375 // emit a NOP after it.
2376 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002377 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2378 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2379 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002380
2381 return false;
2382}
2383
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002384/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002385template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002386 unsigned BitNum = findFirstSet(x);
2387
2388 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2389}
2390
2391/// Load (or add) an immediate into a register.
2392///
2393/// @param ImmValue The immediate to load.
2394/// @param DstReg The register that will hold the immediate.
2395/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2396/// for a simple initialization.
2397/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2398/// @param IsAddress True if the immediate represents an address. False if it
2399/// is an integer.
2400/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002401bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002402 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002403 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2404 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002405 MipsTargetStreamer &TOut = getTargetStreamer();
2406
Toma Tabacu00e98672015-05-01 12:19:27 +00002407 if (!Is32BitImm && !isGP64bit()) {
2408 Error(IDLoc, "instruction requires a 64-bit architecture");
2409 return true;
2410 }
2411
Daniel Sanders03f9c012015-07-14 12:24:22 +00002412 if (Is32BitImm) {
2413 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2414 // Sign extend up to 64-bit so that the predicates match the hardware
2415 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2416 // true.
2417 ImmValue = SignExtend64<32>(ImmValue);
2418 } else {
2419 Error(IDLoc, "instruction requires a 32-bit immediate");
2420 return true;
2421 }
2422 }
2423
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002424 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2425 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2426
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002427 bool UseSrcReg = false;
2428 if (SrcReg != Mips::NoRegister)
2429 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002430
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002431 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002432 if (UseSrcReg &&
2433 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002434 // At this point we need AT to perform the expansions and we exit if it is
2435 // not available.
2436 unsigned ATReg = getATReg(IDLoc);
2437 if (!ATReg)
2438 return true;
2439 TmpReg = ATReg;
2440 }
2441
Daniel Sanders03f9c012015-07-14 12:24:22 +00002442 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002443 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002444 SrcReg = ZeroReg;
2445
2446 // This doesn't quite follow the usual ABI expectations for N32 but matches
2447 // traditional assembler behaviour. N32 would normally use addiu for both
2448 // integers and addresses.
2449 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002450 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002451 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002452 }
2453
Daniel Sandersa736b372016-04-29 13:33:12 +00002454 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002455 return false;
2456 }
2457
2458 if (isUInt<16>(ImmValue)) {
2459 unsigned TmpReg = DstReg;
2460 if (SrcReg == DstReg) {
2461 TmpReg = getATReg(IDLoc);
2462 if (!TmpReg)
2463 return true;
2464 }
2465
Daniel Sandersa736b372016-04-29 13:33:12 +00002466 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002467 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002468 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002469 return false;
2470 }
2471
2472 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002473 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002474
Toma Tabacu79588102015-04-29 10:19:56 +00002475 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2476 uint16_t Bits15To0 = ImmValue & 0xffff;
2477
Toma Tabacua3d056f2015-05-15 09:42:11 +00002478 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002479 // Traditional behaviour seems to special case this particular value. It's
2480 // not clear why other masks are handled differently.
2481 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002482 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2483 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002484 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002485 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002486 return false;
2487 }
2488
2489 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002490 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002491 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2492 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002493 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002494 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002495 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002496 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002497 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002498 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002499
Daniel Sandersa736b372016-04-29 13:33:12 +00002500 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002501 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002502 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002503 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002504 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002505 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002506 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002507
2508 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2509 if (Is32BitImm) {
2510 Error(IDLoc, "instruction requires a 32-bit immediate");
2511 return true;
2512 }
2513
2514 // Traditionally, these immediates are shifted as little as possible and as
2515 // such we align the most significant bit to bit 15 of our temporary.
2516 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2517 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2518 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2519 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002520 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2521 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002522
2523 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002524 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002525
2526 return false;
2527 }
2528
2529 warnIfNoMacro(IDLoc);
2530
2531 // The remaining case is packed with a sequence of dsll and ori with zeros
2532 // being omitted and any neighbouring dsll's being coalesced.
2533 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2534
2535 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2536 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002537 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002538 return false;
2539
2540 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2541 // skip it and defer the shift to the next chunk.
2542 unsigned ShiftCarriedForwards = 16;
2543 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2544 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2545
2546 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002547 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2548 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002549 ShiftCarriedForwards = 0;
2550 }
2551
2552 ShiftCarriedForwards += 16;
2553 }
2554 ShiftCarriedForwards -= 16;
2555
2556 // Finish any remaining shifts left by trailing zeros.
2557 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002558 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002559
2560 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002561 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002562
Matheus Almeida3813d572014-06-19 14:39:14 +00002563 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002564}
Jack Carter92995f12012-10-06 00:53:28 +00002565
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002566bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002567 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002568 const MCOperand &ImmOp = Inst.getOperand(1);
2569 assert(ImmOp.isImm() && "expected immediate operand kind");
2570 const MCOperand &DstRegOp = Inst.getOperand(0);
2571 assert(DstRegOp.isReg() && "expected register operand kind");
2572
2573 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002574 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002575 return true;
2576
2577 return false;
2578}
2579
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002580bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2581 const MCOperand &Offset,
2582 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002583 MCStreamer &Out,
2584 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002585 // la can't produce a usable address when addresses are 64-bit.
2586 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2587 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2588 // We currently can't do this because we depend on the equality
2589 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2590 Error(IDLoc, "la used to load 64-bit address");
2591 // Continue as if we had 'dla' instead.
2592 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002593 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002594 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002595
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002596 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002597 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002598 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002599 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002600 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002601
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002602 if (!Offset.isImm())
2603 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002604 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002605
Scott Egerton24557012016-01-21 15:11:01 +00002606 if (!ABI.ArePtrs64bit()) {
2607 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2608 Is32BitAddress = true;
2609 }
2610
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002611 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002612 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002613}
2614
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002615bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2616 unsigned DstReg, unsigned SrcReg,
2617 bool Is32BitSym, SMLoc IDLoc,
2618 MCStreamer &Out,
2619 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002620 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002621 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002622 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002623
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002624 if (inPicMode() && ABI.IsO32()) {
2625 MCValue Res;
2626 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2627 Error(IDLoc, "expected relocatable expression");
2628 return true;
2629 }
2630 if (Res.getSymB() != nullptr) {
2631 Error(IDLoc, "expected relocatable expression with only one symbol");
2632 return true;
2633 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002634
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002635 // The case where the result register is $25 is somewhat special. If the
2636 // symbol in the final relocation is external and not modified with a
2637 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2638 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2639 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2640 !Res.getSymA()->getSymbol().isTemporary()) {
2641 const MCExpr *CallExpr =
2642 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2643 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2644 MCOperand::createExpr(CallExpr), IDLoc, STI);
2645 return false;
2646 }
2647
2648 // The remaining cases are:
2649 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2650 // >addiu $tmp, $tmp, %lo(offset)
2651 // >addiu $rd, $tmp, $rs
2652 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2653 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2654 // >addiu $rd, $tmp, $rs
2655 // The addiu's marked with a '>' may be omitted if they are redundant. If
2656 // this happens then the last instruction must use $rd as the result
2657 // register.
2658 const MipsMCExpr *GotExpr =
2659 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2660 const MCExpr *LoExpr = nullptr;
2661 if (Res.getSymA()->getSymbol().isInSection() ||
2662 Res.getSymA()->getSymbol().isTemporary())
2663 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2664 else if (Res.getConstant() != 0) {
2665 // External symbols fully resolve the symbol with just the %got(symbol)
2666 // but we must still account for any offset to the symbol for expressions
2667 // like symbol+8.
2668 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2669 }
2670
2671 unsigned TmpReg = DstReg;
2672 if (UseSrcReg &&
2673 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2674 SrcReg)) {
2675 // If $rs is the same as $rd, we need to use AT.
2676 // If it is not available we exit.
2677 unsigned ATReg = getATReg(IDLoc);
2678 if (!ATReg)
2679 return true;
2680 TmpReg = ATReg;
2681 }
2682
2683 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2684 MCOperand::createExpr(GotExpr), IDLoc, STI);
2685
2686 if (LoExpr)
2687 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2688 IDLoc, STI);
2689
2690 if (UseSrcReg)
2691 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2692
2693 return false;
2694 }
2695
2696 const MipsMCExpr *HiExpr =
2697 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2698 const MipsMCExpr *LoExpr =
2699 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002700
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002701 // This is the 64-bit symbol address expansion.
2702 if (ABI.ArePtrs64bit() && isGP64bit()) {
2703 // We always need AT for the 64-bit expansion.
2704 // If it is not available we exit.
2705 unsigned ATReg = getATReg(IDLoc);
2706 if (!ATReg)
2707 return true;
2708
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002709 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002710 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002711 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002712 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002713
Scott Egerton24557012016-01-21 15:11:01 +00002714 if (UseSrcReg &&
2715 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2716 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002717 // If $rs is the same as $rd:
2718 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2719 // daddiu $at, $at, %higher(sym)
2720 // dsll $at, $at, 16
2721 // daddiu $at, $at, %hi(sym)
2722 // dsll $at, $at, 16
2723 // daddiu $at, $at, %lo(sym)
2724 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002725 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2726 STI);
2727 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2728 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2729 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2730 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2731 IDLoc, STI);
2732 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2733 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2734 IDLoc, STI);
2735 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002736
2737 return false;
2738 }
2739
2740 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2741 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2742 // lui $at, %hi(sym)
2743 // daddiu $rd, $rd, %higher(sym)
2744 // daddiu $at, $at, %lo(sym)
2745 // dsll32 $rd, $rd, 0
2746 // daddu $rd, $rd, $at
2747 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002748 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2749 STI);
2750 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2751 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2752 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2753 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2754 IDLoc, STI);
2755 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2756 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002757 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002758 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002759
2760 return false;
2761 }
2762
2763 // And now, the 32-bit symbol address expansion:
2764 // If $rs is the same as $rd:
2765 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2766 // ori $at, $at, %lo(sym)
2767 // addu $rd, $at, $rd
2768 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2769 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2770 // ori $rd, $rd, %lo(sym)
2771 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002772 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002773 if (UseSrcReg &&
2774 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002775 // If $rs is the same as $rd, we need to use AT.
2776 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002777 unsigned ATReg = getATReg(IDLoc);
2778 if (!ATReg)
2779 return true;
2780 TmpReg = ATReg;
2781 }
2782
Daniel Sandersa736b372016-04-29 13:33:12 +00002783 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2784 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2785 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002786
Toma Tabacufb9d1252015-06-22 12:08:39 +00002787 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002788 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002789 else
Scott Egerton24557012016-01-21 15:11:01 +00002790 assert(
2791 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002792
Toma Tabacu674825c2015-06-16 12:16:24 +00002793 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002794}
2795
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002796bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2797 MCStreamer &Out,
2798 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002799 MipsTargetStreamer &TOut = getTargetStreamer();
2800
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002801 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2802 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002803
2804 MCOperand Offset = Inst.getOperand(0);
2805 if (Offset.isExpr()) {
2806 Inst.clear();
2807 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002808 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2809 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2810 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002811 } else {
2812 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002813 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002814 // If offset fits into 11 bits then this instruction becomes microMIPS
2815 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002816 if (inMicroMipsMode())
2817 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002818 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002819 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002820 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002821 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002822 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002823 Inst.clear();
2824 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002825 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2826 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2827 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002828 }
2829 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002830 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002831
Zoran Jovanovicada70912015-09-07 11:56:37 +00002832 // If .set reorder is active and branch instruction has a delay slot,
2833 // emit a NOP after it.
2834 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2835 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002836 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002837
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002838 return false;
2839}
2840
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002841bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2842 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002843 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002844 const MCOperand &DstRegOp = Inst.getOperand(0);
2845 assert(DstRegOp.isReg() && "expected register operand kind");
2846
2847 const MCOperand &ImmOp = Inst.getOperand(1);
2848 assert(ImmOp.isImm() && "expected immediate operand kind");
2849
2850 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002851 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2852 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002853
2854 unsigned OpCode = 0;
2855 switch(Inst.getOpcode()) {
2856 case Mips::BneImm:
2857 OpCode = Mips::BNE;
2858 break;
2859 case Mips::BeqImm:
2860 OpCode = Mips::BEQ;
2861 break;
2862 default:
2863 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2864 break;
2865 }
2866
2867 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002868 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002869 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2870 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002871 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002872 warnIfNoMacro(IDLoc);
2873
2874 unsigned ATReg = getATReg(IDLoc);
2875 if (!ATReg)
2876 return true;
2877
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002878 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002879 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002880 return true;
2881
Daniel Sandersa736b372016-04-29 13:33:12 +00002882 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002883 }
2884 return false;
2885}
2886
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002887void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002888 const MCSubtargetInfo *STI, bool IsLoad,
2889 bool IsImmOpnd) {
2890 if (IsLoad) {
2891 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2892 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002893 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002894 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2895}
2896
2897void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2898 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2899 MipsTargetStreamer &TOut = getTargetStreamer();
2900
2901 unsigned DstReg = Inst.getOperand(0).getReg();
2902 unsigned BaseReg = Inst.getOperand(1).getReg();
2903
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002904 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002905 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2906 unsigned DstRegClassID =
2907 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2908 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2909 (DstRegClassID == Mips::GPR64RegClassID);
2910
2911 if (IsImmOpnd) {
2912 // Try to use DstReg as the temporary.
2913 if (IsGPR && (BaseReg != DstReg)) {
2914 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2915 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2916 STI);
2917 return;
2918 }
2919
Matheus Almeida7de68e72014-06-18 14:46:05 +00002920 // At this point we need AT to perform the expansions and we exit if it is
2921 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002922 unsigned ATReg = getATReg(IDLoc);
2923 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002924 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002925
2926 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2927 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2928 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002929 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002930
Daniel Sandersfba875f2016-04-29 13:43:45 +00002931 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002932 MCOperand LoOperand = MCOperand::createExpr(
2933 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2934 MCOperand HiOperand = MCOperand::createExpr(
2935 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002936
2937 // Try to use DstReg as the temporary.
2938 if (IsGPR && (BaseReg != DstReg)) {
2939 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2940 LoOperand, DstReg, IDLoc, STI);
2941 return;
2942 }
2943
2944 // At this point we need AT to perform the expansions and we exit if it is
2945 // not available.
2946 unsigned ATReg = getATReg(IDLoc);
2947 if (!ATReg)
2948 return;
2949
2950 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2951 LoOperand, ATReg, IDLoc, STI);
2952}
2953
2954void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2955 const MCSubtargetInfo *STI,
2956 bool IsImmOpnd) {
2957 MipsTargetStreamer &TOut = getTargetStreamer();
2958
2959 unsigned SrcReg = Inst.getOperand(0).getReg();
2960 unsigned BaseReg = Inst.getOperand(1).getReg();
2961
Daniel Sanders241c6792016-05-12 14:01:50 +00002962 if (IsImmOpnd) {
2963 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2964 Inst.getOperand(2).getImm(),
2965 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2966 return;
2967 }
2968
Daniel Sandersfba875f2016-04-29 13:43:45 +00002969 unsigned ATReg = getATReg(IDLoc);
2970 if (!ATReg)
2971 return;
2972
Daniel Sandersfba875f2016-04-29 13:43:45 +00002973 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002974 MCOperand LoOperand = MCOperand::createExpr(
2975 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2976 MCOperand HiOperand = MCOperand::createExpr(
2977 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002978 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2979 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002980}
2981
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002982bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2983 MCStreamer &Out,
2984 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002985 unsigned OpNum = Inst.getNumOperands();
2986 unsigned Opcode = Inst.getOpcode();
2987 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2988
Eugene Zelenkodde94e42017-01-30 23:21:32 +00002989 assert(Inst.getOperand(OpNum - 1).isImm() &&
2990 Inst.getOperand(OpNum - 2).isReg() &&
2991 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002992
2993 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2994 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002995 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2996 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2997 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2998 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002999 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003000 if (inMicroMipsMode() && hasMips32r6())
3001 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3002 else
3003 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3004 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003005
3006 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003007 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003008 return false;
3009}
3010
Toma Tabacu1a108322015-06-17 13:20:24 +00003011bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003012 MCStreamer &Out,
3013 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003014 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003015 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003016 unsigned PseudoOpcode = Inst.getOpcode();
3017 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003018 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003019 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3020
3021 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003022 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003023
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003024 unsigned TrgReg;
3025 if (TrgOp.isReg())
3026 TrgReg = TrgOp.getReg();
3027 else if (TrgOp.isImm()) {
3028 warnIfNoMacro(IDLoc);
3029 EmittedNoMacroWarning = true;
3030
3031 TrgReg = getATReg(IDLoc);
3032 if (!TrgReg)
3033 return true;
3034
3035 switch(PseudoOpcode) {
3036 default:
3037 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3038 case Mips::BLTImmMacro:
3039 PseudoOpcode = Mips::BLT;
3040 break;
3041 case Mips::BLEImmMacro:
3042 PseudoOpcode = Mips::BLE;
3043 break;
3044 case Mips::BGEImmMacro:
3045 PseudoOpcode = Mips::BGE;
3046 break;
3047 case Mips::BGTImmMacro:
3048 PseudoOpcode = Mips::BGT;
3049 break;
3050 case Mips::BLTUImmMacro:
3051 PseudoOpcode = Mips::BLTU;
3052 break;
3053 case Mips::BLEUImmMacro:
3054 PseudoOpcode = Mips::BLEU;
3055 break;
3056 case Mips::BGEUImmMacro:
3057 PseudoOpcode = Mips::BGEU;
3058 break;
3059 case Mips::BGTUImmMacro:
3060 PseudoOpcode = Mips::BGTU;
3061 break;
3062 case Mips::BLTLImmMacro:
3063 PseudoOpcode = Mips::BLTL;
3064 break;
3065 case Mips::BLELImmMacro:
3066 PseudoOpcode = Mips::BLEL;
3067 break;
3068 case Mips::BGELImmMacro:
3069 PseudoOpcode = Mips::BGEL;
3070 break;
3071 case Mips::BGTLImmMacro:
3072 PseudoOpcode = Mips::BGTL;
3073 break;
3074 case Mips::BLTULImmMacro:
3075 PseudoOpcode = Mips::BLTUL;
3076 break;
3077 case Mips::BLEULImmMacro:
3078 PseudoOpcode = Mips::BLEUL;
3079 break;
3080 case Mips::BGEULImmMacro:
3081 PseudoOpcode = Mips::BGEUL;
3082 break;
3083 case Mips::BGTULImmMacro:
3084 PseudoOpcode = Mips::BGTUL;
3085 break;
3086 }
3087
3088 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003089 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003090 return true;
3091 }
3092
Toma Tabacu1a108322015-06-17 13:20:24 +00003093 switch (PseudoOpcode) {
3094 case Mips::BLT:
3095 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003096 case Mips::BLTL:
3097 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003098 AcceptsEquality = false;
3099 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003100 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3101 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003102 ZeroSrcOpcode = Mips::BGTZ;
3103 ZeroTrgOpcode = Mips::BLTZ;
3104 break;
3105 case Mips::BLE:
3106 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003107 case Mips::BLEL:
3108 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003109 AcceptsEquality = true;
3110 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003111 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3112 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003113 ZeroSrcOpcode = Mips::BGEZ;
3114 ZeroTrgOpcode = Mips::BLEZ;
3115 break;
3116 case Mips::BGE:
3117 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003118 case Mips::BGEL:
3119 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003120 AcceptsEquality = true;
3121 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003122 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3123 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003124 ZeroSrcOpcode = Mips::BLEZ;
3125 ZeroTrgOpcode = Mips::BGEZ;
3126 break;
3127 case Mips::BGT:
3128 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003129 case Mips::BGTL:
3130 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003131 AcceptsEquality = false;
3132 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003133 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3134 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003135 ZeroSrcOpcode = Mips::BLTZ;
3136 ZeroTrgOpcode = Mips::BGTZ;
3137 break;
3138 default:
3139 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3140 }
3141
Toma Tabacu1a108322015-06-17 13:20:24 +00003142 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3143 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3144 if (IsSrcRegZero && IsTrgRegZero) {
3145 // FIXME: All of these Opcode-specific if's are needed for compatibility
3146 // with GAS' behaviour. However, they may not generate the most efficient
3147 // code in some circumstances.
3148 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003149 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3150 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003151 return false;
3152 }
3153 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003154 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3155 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003156 Warning(IDLoc, "branch is always taken");
3157 return false;
3158 }
3159 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003160 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3161 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003162 Warning(IDLoc, "branch is always taken");
3163 return false;
3164 }
3165 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003166 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3167 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003168 return false;
3169 }
3170 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003171 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3172 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003173 return false;
3174 }
3175 if (AcceptsEquality) {
3176 // If both registers are $0 and the pseudo-branch accepts equality, it
3177 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003178 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3179 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003180 Warning(IDLoc, "branch is always taken");
3181 return false;
3182 }
3183 // If both registers are $0 and the pseudo-branch does not accept
3184 // equality, it will never be taken, so we don't have to emit anything.
3185 return false;
3186 }
3187 if (IsSrcRegZero || IsTrgRegZero) {
3188 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3189 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3190 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3191 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3192 // the pseudo-branch will never be taken, so we don't emit anything.
3193 // This only applies to unsigned pseudo-branches.
3194 return false;
3195 }
3196 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3197 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3198 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3199 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3200 // the pseudo-branch will always be taken, so we emit an unconditional
3201 // branch.
3202 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003203 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3204 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003205 Warning(IDLoc, "branch is always taken");
3206 return false;
3207 }
3208 if (IsUnsigned) {
3209 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3210 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3211 // the pseudo-branch will be taken only when the non-zero register is
3212 // different from 0, so we emit a BNEZ.
3213 //
3214 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3215 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3216 // the pseudo-branch will be taken only when the non-zero register is
3217 // equal to 0, so we emit a BEQZ.
3218 //
3219 // Because only BLEU and BGEU branch on equality, we can use the
3220 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003221 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3222 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3223 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003224 return false;
3225 }
3226 // If we have a signed pseudo-branch and one of the registers is $0,
3227 // we can use an appropriate compare-to-zero branch. We select which one
3228 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003229 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3230 IsSrcRegZero ? TrgReg : SrcReg,
3231 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003232 return false;
3233 }
3234
3235 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3236 // expansions. If it is not available, we return.
3237 unsigned ATRegNum = getATReg(IDLoc);
3238 if (!ATRegNum)
3239 return true;
3240
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003241 if (!EmittedNoMacroWarning)
3242 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003243
3244 // SLT fits well with 2 of our 4 pseudo-branches:
3245 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3246 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3247 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3248 // This is accomplished by using a BNEZ with the result of the SLT.
3249 //
3250 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3251 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3252 // Because only BGE and BLE branch on equality, we can use the
3253 // AcceptsEquality variable to decide when to emit the BEQZ.
3254 // Note that the order of the SLT arguments doesn't change between
3255 // opposites.
3256 //
3257 // The same applies to the unsigned variants, except that SLTu is used
3258 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003259 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3260 ReverseOrderSLT ? TrgReg : SrcReg,
3261 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003262
Daniel Sandersa736b372016-04-29 13:33:12 +00003263 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3264 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3265 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3266 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003267 return false;
3268}
3269
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003270bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3271 const MCSubtargetInfo *STI, const bool IsMips64,
3272 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003273 MipsTargetStreamer &TOut = getTargetStreamer();
3274
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003275 warnIfNoMacro(IDLoc);
3276
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003277 const MCOperand &RdRegOp = Inst.getOperand(0);
3278 assert(RdRegOp.isReg() && "expected register operand kind");
3279 unsigned RdReg = RdRegOp.getReg();
3280
3281 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003282 assert(RsRegOp.isReg() && "expected register operand kind");
3283 unsigned RsReg = RsRegOp.getReg();
3284
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003285 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003286 assert(RtRegOp.isReg() && "expected register operand kind");
3287 unsigned RtReg = RtRegOp.getReg();
3288 unsigned DivOp;
3289 unsigned ZeroReg;
3290
3291 if (IsMips64) {
3292 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3293 ZeroReg = Mips::ZERO_64;
3294 } else {
3295 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3296 ZeroReg = Mips::ZERO;
3297 }
3298
3299 bool UseTraps = useTraps();
3300
3301 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3302 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3303 Warning(IDLoc, "dividing zero by zero");
3304 if (IsMips64) {
3305 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3306 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003307 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003308 return false;
3309 }
3310
Daniel Sandersa736b372016-04-29 13:33:12 +00003311 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003312 return false;
3313 }
3314 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003315 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003316 return false;
3317 }
3318 }
3319
3320 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3321 Warning(IDLoc, "division by zero");
3322 if (Signed) {
3323 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003324 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003325 return false;
3326 }
3327
Daniel Sandersa736b372016-04-29 13:33:12 +00003328 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003329 return false;
3330 }
3331 }
3332
3333 // FIXME: The values for these two BranchTarget variables may be different in
3334 // micromips. These magic numbers need to be removed.
3335 unsigned BranchTargetNoTraps;
3336 unsigned BranchTarget;
3337
3338 if (UseTraps) {
3339 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003340 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003341 } else {
3342 BranchTarget = IsMips64 ? 20 : 16;
3343 BranchTargetNoTraps = 8;
3344 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003345 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003346 }
3347
Daniel Sandersa736b372016-04-29 13:33:12 +00003348 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003349
3350 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003351 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003352
3353 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003354 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003355 return false;
3356 }
3357
3358 unsigned ATReg = getATReg(IDLoc);
3359 if (!ATReg)
3360 return true;
3361
Daniel Sandersa736b372016-04-29 13:33:12 +00003362 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003363 if (IsMips64) {
3364 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003365 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3366 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3367 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003368 } else {
3369 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003370 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3371 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003372 }
3373
3374 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003375 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003376 else {
3377 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003378 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3379 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3380 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003381 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003382 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003383 return false;
3384}
3385
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003386bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003387 SMLoc IDLoc, MCStreamer &Out,
3388 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003389 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003390
3391 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3392 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3393 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3394
3395 unsigned FirstReg = Inst.getOperand(0).getReg();
3396 unsigned SecondReg = Inst.getOperand(1).getReg();
3397 unsigned ThirdReg = Inst.getOperand(2).getReg();
3398
3399 if (hasMips1() && !hasMips2()) {
3400 unsigned ATReg = getATReg(IDLoc);
3401 if (!ATReg)
3402 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003403 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3404 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3405 TOut.emitNop(IDLoc, STI);
3406 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3407 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3408 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3409 TOut.emitNop(IDLoc, STI);
3410 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3411 : Mips::CVT_W_S,
3412 FirstReg, SecondReg, IDLoc, STI);
3413 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3414 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003415 return false;
3416 }
3417
Daniel Sandersa736b372016-04-29 13:33:12 +00003418 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3419 : Mips::TRUNC_W_S,
3420 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003421
3422 return false;
3423}
3424
Daniel Sanders6394ee52015-10-15 14:52:58 +00003425bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003426 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003427 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003428 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003429 }
3430
Toma Tabacud88d79c2015-06-23 14:39:42 +00003431 const MCOperand &DstRegOp = Inst.getOperand(0);
3432 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003433 const MCOperand &SrcRegOp = Inst.getOperand(1);
3434 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003435 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3436 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3437
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003438 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00003439 unsigned DstReg = DstRegOp.getReg();
3440 unsigned SrcReg = SrcRegOp.getReg();
3441 int64_t OffsetValue = OffsetImmOp.getImm();
3442
3443 // NOTE: We always need AT for ULHU, as it is always used as the source
3444 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003445 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003446 unsigned ATReg = getATReg(IDLoc);
3447 if (!ATReg)
3448 return true;
3449
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003450 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3451 if (IsLargeOffset) {
3452 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3453 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003454 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003455 }
3456
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003457 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
3458 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3459 if (isLittle())
3460 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003461
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003462 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
3463 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003464
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003465 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
3466 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003467
Daniel Sandersa736b372016-04-29 13:33:12 +00003468 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003469 FirstOffset, IDLoc, STI);
3470 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003471 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003472 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003473
3474 return false;
3475}
3476
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003477bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003478 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003479 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003480 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003481 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003482
3483 const MCOperand &DstRegOp = Inst.getOperand(0);
3484 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003485 const MCOperand &SrcRegOp = Inst.getOperand(1);
3486 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003487 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3488 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3489
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003490 MipsTargetStreamer &TOut = getTargetStreamer();
3491 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003492 unsigned SrcReg = SrcRegOp.getReg();
3493 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003494
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003495 warnIfNoMacro(IDLoc);
3496 unsigned ATReg = getATReg(IDLoc);
3497 if (!ATReg)
3498 return true;
3499
3500 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3501 if (IsLargeOffset) {
3502 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3503 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003504 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003505 }
3506
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003507 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3508 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
3509 if (isLittle())
3510 std::swap(FirstOffset, SecondOffset);
3511
3512 if (IsLargeOffset) {
3513 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
3514 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
3515 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
3516 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
3517 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
3518 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003519 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003520 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
3521 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
3522 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003523 }
3524
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003525 return false;
3526}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003527
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003528bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3529 const MCSubtargetInfo *STI) {
3530 if (hasMips32r6() || hasMips64r6()) {
3531 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3532 }
3533
3534 const MCOperand &DstRegOp = Inst.getOperand(0);
3535 assert(DstRegOp.isReg() && "expected register operand kind");
3536 const MCOperand &SrcRegOp = Inst.getOperand(1);
3537 assert(SrcRegOp.isReg() && "expected register operand kind");
3538 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3539 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3540
3541 MipsTargetStreamer &TOut = getTargetStreamer();
3542 unsigned DstReg = DstRegOp.getReg();
3543 unsigned SrcReg = SrcRegOp.getReg();
3544 int64_t OffsetValue = OffsetImmOp.getImm();
3545
3546 // Compute left/right load/store offsets.
3547 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
3548 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
3549 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
3550 if (isLittle())
3551 std::swap(LxlOffset, LxrOffset);
3552
3553 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
3554 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
3555 unsigned TmpReg = SrcReg;
3556 if (IsLargeOffset || DoMove) {
3557 warnIfNoMacro(IDLoc);
3558 TmpReg = getATReg(IDLoc);
3559 if (!TmpReg)
3560 return true;
3561 }
3562
3563 if (IsLargeOffset) {
3564 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
3565 IDLoc, Out, STI))
3566 return true;
3567 }
3568
3569 if (DoMove)
3570 std::swap(DstReg, TmpReg);
3571
3572 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
3573 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
3574 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
3575 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
3576
3577 if (DoMove)
3578 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003579
3580 return false;
3581}
3582
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003583bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003584 MCStreamer &Out,
3585 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003586 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003587
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003588 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3589 assert(Inst.getOperand(0).isReg() &&
3590 Inst.getOperand(1).isReg() &&
3591 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003592
3593 unsigned ATReg = Mips::NoRegister;
3594 unsigned FinalDstReg = Mips::NoRegister;
3595 unsigned DstReg = Inst.getOperand(0).getReg();
3596 unsigned SrcReg = Inst.getOperand(1).getReg();
3597 int64_t ImmValue = Inst.getOperand(2).getImm();
3598
3599 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3600
3601 unsigned FinalOpcode = Inst.getOpcode();
3602
3603 if (DstReg == SrcReg) {
3604 ATReg = getATReg(Inst.getLoc());
3605 if (!ATReg)
3606 return true;
3607 FinalDstReg = DstReg;
3608 DstReg = ATReg;
3609 }
3610
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003611 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003612 switch (FinalOpcode) {
3613 default:
3614 llvm_unreachable("unimplemented expansion");
3615 case (Mips::ADDi):
3616 FinalOpcode = Mips::ADD;
3617 break;
3618 case (Mips::ADDiu):
3619 FinalOpcode = Mips::ADDu;
3620 break;
3621 case (Mips::ANDi):
3622 FinalOpcode = Mips::AND;
3623 break;
3624 case (Mips::NORImm):
3625 FinalOpcode = Mips::NOR;
3626 break;
3627 case (Mips::ORi):
3628 FinalOpcode = Mips::OR;
3629 break;
3630 case (Mips::SLTi):
3631 FinalOpcode = Mips::SLT;
3632 break;
3633 case (Mips::SLTiu):
3634 FinalOpcode = Mips::SLTu;
3635 break;
3636 case (Mips::XORi):
3637 FinalOpcode = Mips::XOR;
3638 break;
3639 }
3640
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003641 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003642 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003643 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003644 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003645 return false;
3646 }
3647 return true;
3648}
3649
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003650bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3651 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003652 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003653 unsigned ATReg = Mips::NoRegister;
3654 unsigned DReg = Inst.getOperand(0).getReg();
3655 unsigned SReg = Inst.getOperand(1).getReg();
3656 unsigned TReg = Inst.getOperand(2).getReg();
3657 unsigned TmpReg = DReg;
3658
3659 unsigned FirstShift = Mips::NOP;
3660 unsigned SecondShift = Mips::NOP;
3661
3662 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003663 if (DReg == SReg) {
3664 TmpReg = getATReg(Inst.getLoc());
3665 if (!TmpReg)
3666 return true;
3667 }
3668
3669 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003670 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3671 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003672 return false;
3673 }
3674
3675 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003676 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003677 return false;
3678 }
3679
3680 return true;
3681 }
3682
3683 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003684 switch (Inst.getOpcode()) {
3685 default:
3686 llvm_unreachable("unexpected instruction opcode");
3687 case Mips::ROL:
3688 FirstShift = Mips::SRLV;
3689 SecondShift = Mips::SLLV;
3690 break;
3691 case Mips::ROR:
3692 FirstShift = Mips::SLLV;
3693 SecondShift = Mips::SRLV;
3694 break;
3695 }
3696
3697 ATReg = getATReg(Inst.getLoc());
3698 if (!ATReg)
3699 return true;
3700
Daniel Sandersa736b372016-04-29 13:33:12 +00003701 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3702 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3703 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3704 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003705
3706 return false;
3707 }
3708
3709 return true;
3710}
3711
3712bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003713 MCStreamer &Out,
3714 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003715 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003716 unsigned ATReg = Mips::NoRegister;
3717 unsigned DReg = Inst.getOperand(0).getReg();
3718 unsigned SReg = Inst.getOperand(1).getReg();
3719 int64_t ImmValue = Inst.getOperand(2).getImm();
3720
3721 unsigned FirstShift = Mips::NOP;
3722 unsigned SecondShift = Mips::NOP;
3723
3724 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003725 if (Inst.getOpcode() == Mips::ROLImm) {
3726 uint64_t MaxShift = 32;
3727 uint64_t ShiftValue = ImmValue;
3728 if (ImmValue != 0)
3729 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003730 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003731 return false;
3732 }
3733
3734 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003735 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003736 return false;
3737 }
3738
3739 return true;
3740 }
3741
3742 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003743 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003744 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003745 return false;
3746 }
3747
3748 switch (Inst.getOpcode()) {
3749 default:
3750 llvm_unreachable("unexpected instruction opcode");
3751 case Mips::ROLImm:
3752 FirstShift = Mips::SLL;
3753 SecondShift = Mips::SRL;
3754 break;
3755 case Mips::RORImm:
3756 FirstShift = Mips::SRL;
3757 SecondShift = Mips::SLL;
3758 break;
3759 }
3760
3761 ATReg = getATReg(Inst.getLoc());
3762 if (!ATReg)
3763 return true;
3764
Daniel Sandersa736b372016-04-29 13:33:12 +00003765 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3766 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3767 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003768
3769 return false;
3770 }
3771
3772 return true;
3773}
3774
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003775bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3776 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003777 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003778 unsigned ATReg = Mips::NoRegister;
3779 unsigned DReg = Inst.getOperand(0).getReg();
3780 unsigned SReg = Inst.getOperand(1).getReg();
3781 unsigned TReg = Inst.getOperand(2).getReg();
3782 unsigned TmpReg = DReg;
3783
3784 unsigned FirstShift = Mips::NOP;
3785 unsigned SecondShift = Mips::NOP;
3786
3787 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003788 if (TmpReg == SReg) {
3789 TmpReg = getATReg(Inst.getLoc());
3790 if (!TmpReg)
3791 return true;
3792 }
3793
3794 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003795 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3796 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003797 return false;
3798 }
3799
3800 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003801 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003802 return false;
3803 }
3804
3805 return true;
3806 }
3807
3808 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003809 switch (Inst.getOpcode()) {
3810 default:
3811 llvm_unreachable("unexpected instruction opcode");
3812 case Mips::DROL:
3813 FirstShift = Mips::DSRLV;
3814 SecondShift = Mips::DSLLV;
3815 break;
3816 case Mips::DROR:
3817 FirstShift = Mips::DSLLV;
3818 SecondShift = Mips::DSRLV;
3819 break;
3820 }
3821
3822 ATReg = getATReg(Inst.getLoc());
3823 if (!ATReg)
3824 return true;
3825
Daniel Sandersa736b372016-04-29 13:33:12 +00003826 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3827 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3828 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3829 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003830
3831 return false;
3832 }
3833
3834 return true;
3835}
3836
3837bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003838 MCStreamer &Out,
3839 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003840 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003841 unsigned ATReg = Mips::NoRegister;
3842 unsigned DReg = Inst.getOperand(0).getReg();
3843 unsigned SReg = Inst.getOperand(1).getReg();
3844 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3845
3846 unsigned FirstShift = Mips::NOP;
3847 unsigned SecondShift = Mips::NOP;
3848
3849 MCInst TmpInst;
3850
3851 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003852 unsigned FinalOpcode = Mips::NOP;
3853 if (ImmValue == 0)
3854 FinalOpcode = Mips::DROTR;
3855 else if (ImmValue % 32 == 0)
3856 FinalOpcode = Mips::DROTR32;
3857 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3858 if (Inst.getOpcode() == Mips::DROLImm)
3859 FinalOpcode = Mips::DROTR32;
3860 else
3861 FinalOpcode = Mips::DROTR;
3862 } else if (ImmValue >= 33) {
3863 if (Inst.getOpcode() == Mips::DROLImm)
3864 FinalOpcode = Mips::DROTR;
3865 else
3866 FinalOpcode = Mips::DROTR32;
3867 }
3868
3869 uint64_t ShiftValue = ImmValue % 32;
3870 if (Inst.getOpcode() == Mips::DROLImm)
3871 ShiftValue = (32 - ImmValue % 32) % 32;
3872
Daniel Sandersa736b372016-04-29 13:33:12 +00003873 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003874
3875 return false;
3876 }
3877
3878 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003879 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003880 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003881 return false;
3882 }
3883
3884 switch (Inst.getOpcode()) {
3885 default:
3886 llvm_unreachable("unexpected instruction opcode");
3887 case Mips::DROLImm:
3888 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3889 FirstShift = Mips::DSLL;
3890 SecondShift = Mips::DSRL32;
3891 }
3892 if (ImmValue == 32) {
3893 FirstShift = Mips::DSLL32;
3894 SecondShift = Mips::DSRL32;
3895 }
3896 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3897 FirstShift = Mips::DSLL32;
3898 SecondShift = Mips::DSRL;
3899 }
3900 break;
3901 case Mips::DRORImm:
3902 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3903 FirstShift = Mips::DSRL;
3904 SecondShift = Mips::DSLL32;
3905 }
3906 if (ImmValue == 32) {
3907 FirstShift = Mips::DSRL32;
3908 SecondShift = Mips::DSLL32;
3909 }
3910 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3911 FirstShift = Mips::DSRL32;
3912 SecondShift = Mips::DSLL;
3913 }
3914 break;
3915 }
3916
3917 ATReg = getATReg(Inst.getLoc());
3918 if (!ATReg)
3919 return true;
3920
Daniel Sandersa736b372016-04-29 13:33:12 +00003921 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3922 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3923 Inst.getLoc(), STI);
3924 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003925
3926 return false;
3927 }
3928
3929 return true;
3930}
3931
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003932bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3933 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003934 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003935 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3936 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3937
Daniel Sandersa736b372016-04-29 13:33:12 +00003938 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003939 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003940 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003941 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003942 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3943 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003944
3945 return false;
3946}
3947
Simon Dardisaff4d142016-10-18 14:28:00 +00003948static unsigned nextReg(unsigned Reg) {
3949 switch (Reg) {
3950 case Mips::ZERO: return Mips::AT;
3951 case Mips::AT: return Mips::V0;
3952 case Mips::V0: return Mips::V1;
3953 case Mips::V1: return Mips::A0;
3954 case Mips::A0: return Mips::A1;
3955 case Mips::A1: return Mips::A2;
3956 case Mips::A2: return Mips::A3;
3957 case Mips::A3: return Mips::T0;
3958 case Mips::T0: return Mips::T1;
3959 case Mips::T1: return Mips::T2;
3960 case Mips::T2: return Mips::T3;
3961 case Mips::T3: return Mips::T4;
3962 case Mips::T4: return Mips::T5;
3963 case Mips::T5: return Mips::T6;
3964 case Mips::T6: return Mips::T7;
3965 case Mips::T7: return Mips::S0;
3966 case Mips::S0: return Mips::S1;
3967 case Mips::S1: return Mips::S2;
3968 case Mips::S2: return Mips::S3;
3969 case Mips::S3: return Mips::S4;
3970 case Mips::S4: return Mips::S5;
3971 case Mips::S5: return Mips::S6;
3972 case Mips::S6: return Mips::S7;
3973 case Mips::S7: return Mips::T8;
3974 case Mips::T8: return Mips::T9;
3975 case Mips::T9: return Mips::K0;
3976 case Mips::K0: return Mips::K1;
3977 case Mips::K1: return Mips::GP;
3978 case Mips::GP: return Mips::SP;
3979 case Mips::SP: return Mips::FP;
3980 case Mips::FP: return Mips::RA;
3981 case Mips::RA: return Mips::ZERO;
3982 default: return 0;
3983 }
3984
3985}
3986
3987// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
3988// lw $<reg+1>>, offset+4($reg2)'
3989// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
3990// sw $<reg+1>>, offset+4($reg2)'
3991// for O32.
3992bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
3993 MCStreamer &Out,
3994 const MCSubtargetInfo *STI,
3995 bool IsLoad) {
3996 if (!isABI_O32())
3997 return true;
3998
3999 warnIfNoMacro(IDLoc);
4000
4001 MipsTargetStreamer &TOut = getTargetStreamer();
4002 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4003 unsigned FirstReg = Inst.getOperand(0).getReg();
4004 unsigned SecondReg = nextReg(FirstReg);
4005 unsigned BaseReg = Inst.getOperand(1).getReg();
4006 if (!SecondReg)
4007 return true;
4008
4009 warnIfRegIndexIsAT(FirstReg, IDLoc);
4010
4011 assert(Inst.getOperand(2).isImm() &&
4012 "Offset for load macro is not immediate!");
4013
4014 MCOperand &FirstOffset = Inst.getOperand(2);
4015 signed NextOffset = FirstOffset.getImm() + 4;
4016 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4017
4018 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4019 return true;
4020
4021 // For loads, clobber the base register with the second load instead of the
4022 // first if the BaseReg == FirstReg.
4023 if (FirstReg != BaseReg || !IsLoad) {
4024 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4025 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4026 } else {
4027 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4028 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4029 }
4030
4031 return false;
4032}
4033
Simon Dardis43115a12016-11-21 20:30:41 +00004034bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4035 const MCSubtargetInfo *STI) {
4036
4037 warnIfNoMacro(IDLoc);
4038 MipsTargetStreamer &TOut = getTargetStreamer();
4039
4040 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4041 Inst.getOperand(2).getReg() != Mips::ZERO) {
4042 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4043 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4044 IDLoc, STI);
4045 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4046 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4047 return false;
4048 }
4049
4050 unsigned Reg = 0;
4051 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4052 Reg = Inst.getOperand(2).getReg();
4053 } else {
4054 Reg = Inst.getOperand(1).getReg();
4055 }
4056 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4057 return false;
4058}
4059
4060bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4061 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004062 warnIfNoMacro(IDLoc);
4063 MipsTargetStreamer &TOut = getTargetStreamer();
4064
4065 unsigned Opc;
4066 int64_t Imm = Inst.getOperand(2).getImm();
4067 unsigned Reg = Inst.getOperand(1).getReg();
4068
4069 if (Imm == 0) {
4070 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4071 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4072 return false;
4073 } else {
4074
4075 if (Reg == Mips::ZERO) {
4076 Warning(IDLoc, "comparison is always false");
4077 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4078 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4079 return false;
4080 }
4081
4082 if (Imm > -0x8000 && Imm < 0) {
4083 Imm = -Imm;
4084 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4085 } else {
4086 Opc = Mips::XORi;
4087 }
4088 }
4089 if (!isUInt<16>(Imm)) {
4090 unsigned ATReg = getATReg(IDLoc);
4091 if (!ATReg)
4092 return true;
4093
4094 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4095 Out, STI))
4096 return true;
4097
4098 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4099 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4100 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4101 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4102 return false;
4103 }
4104
4105 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4106 Imm, IDLoc, STI);
4107 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4108 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4109 return false;
4110}
4111
Daniel Sandersc5537422016-07-27 13:49:44 +00004112unsigned
4113MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4114 const OperandVector &Operands) {
4115 switch (Inst.getOpcode()) {
4116 default:
4117 return Match_Success;
4118 case Mips::DATI:
4119 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004120 case Mips::DATI_MM64R6:
4121 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004122 if (static_cast<MipsOperand &>(*Operands[1])
4123 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4124 return Match_Success;
4125 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004126 }
4127}
Simon Dardis730fdb72017-01-16 13:55:58 +00004128
Matheus Almeida595fcab2014-06-11 15:05:56 +00004129unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004130 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004131 // As described by the MIPSR6 spec, daui must not use the zero operand for
4132 // its source operand.
4133 case Mips::DAUI:
4134 case Mips::DAUI_MM64R6:
4135 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4136 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4137 return Match_RequiresNoZeroRegister;
4138 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004139 // As described by the Mips32r2 spec, the registers Rd and Rs for
4140 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004141 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004142 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004143 case Mips::JALR_HB:
4144 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004145 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004146 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4147 return Match_RequiresDifferentSrcAndDst;
4148 return Match_Success;
4149 case Mips::LWP_MM:
4150 case Mips::LWP_MMR6:
4151 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4152 return Match_RequiresDifferentSrcAndDst;
4153 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004154 case Mips::SYNC:
4155 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4156 return Match_NonZeroOperandForSync;
4157 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004158 // As described the MIPSR6 spec, the compact branches that compare registers
4159 // must:
4160 // a) Not use the zero register.
4161 // b) Not use the same register twice.
4162 // c) rs < rt for bnec, beqc.
4163 // NB: For this case, the encoding will swap the operands as their
4164 // ordering doesn't matter. GAS performs this transformation too.
4165 // Hence, that constraint does not have to be enforced.
4166 //
4167 // The compact branches that branch iff the signed addition of two registers
4168 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4169 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004170 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4171 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4172 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4173 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4174 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4175 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004176 case Mips::BLEZC64:
4177 case Mips::BGEZC64:
4178 case Mips::BGTZC64:
4179 case Mips::BLTZC64:
4180 case Mips::BEQZC64:
4181 case Mips::BNEZC64:
4182 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4183 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004184 return Match_RequiresNoZeroRegister;
4185 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004186 case Mips::BGEC: case Mips::BGEC_MMR6:
4187 case Mips::BLTC: case Mips::BLTC_MMR6:
4188 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4189 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4190 case Mips::BEQC: case Mips::BEQC_MMR6:
4191 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004192 case Mips::BGEC64:
4193 case Mips::BLTC64:
4194 case Mips::BGEUC64:
4195 case Mips::BLTUC64:
4196 case Mips::BEQC64:
4197 case Mips::BNEC64:
4198 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4199 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004200 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004201 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4202 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004203 return Match_RequiresNoZeroRegister;
4204 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4205 return Match_RequiresDifferentOperands;
4206 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004207 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004208
4209 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4210 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4211 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4212 return Match_NoFCCRegisterForCurrentISA;
4213
4214 return Match_Success;
4215
Matheus Almeida595fcab2014-06-11 15:05:56 +00004216}
4217
Daniel Sanders52da7af2015-11-06 12:11:03 +00004218static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4219 uint64_t ErrorInfo) {
4220 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4221 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4222 if (ErrorLoc == SMLoc())
4223 return Loc;
4224 return ErrorLoc;
4225 }
4226 return Loc;
4227}
4228
David Blaikie960ea3f2014-06-08 16:18:35 +00004229bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4230 OperandVector &Operands,
4231 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004232 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004233 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004234 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004235 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004236 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004237
4238 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004239 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004240 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004241 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004242 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00004243 case Match_MissingFeature:
4244 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4245 return true;
4246 case Match_InvalidOperand: {
4247 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004248 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004249 if (ErrorInfo >= Operands.size())
4250 return Error(IDLoc, "too few operands for instruction");
4251
Daniel Sanders52da7af2015-11-06 12:11:03 +00004252 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004253 if (ErrorLoc == SMLoc())
4254 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004255 }
4256
4257 return Error(ErrorLoc, "invalid operand for instruction");
4258 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004259 case Match_NonZeroOperandForSync:
4260 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004261 case Match_MnemonicFail:
4262 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004263 case Match_RequiresDifferentSrcAndDst:
4264 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004265 case Match_RequiresDifferentOperands:
4266 return Error(IDLoc, "registers must be different");
4267 case Match_RequiresNoZeroRegister:
4268 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004269 case Match_RequiresSameSrcAndDst:
4270 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00004271 case Match_NoFCCRegisterForCurrentISA:
4272 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4273 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004274 case Match_Immz:
4275 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004276 case Match_UImm1_0:
4277 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4278 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004279 case Match_UImm2_0:
4280 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4281 "expected 2-bit unsigned immediate");
4282 case Match_UImm2_1:
4283 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4284 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004285 case Match_UImm3_0:
4286 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4287 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004288 case Match_UImm4_0:
4289 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4290 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004291 case Match_SImm4_0:
4292 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4293 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004294 case Match_UImm5_0:
4295 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4296 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004297 case Match_SImm5_0:
4298 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4299 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004300 case Match_UImm5_1:
4301 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4302 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004303 case Match_UImm5_32:
4304 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4305 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004306 case Match_UImm5_33:
4307 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4308 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004309 case Match_UImm5_0_Report_UImm6:
4310 // This is used on UImm5 operands that have a corresponding UImm5_32
4311 // operand to avoid confusing the user.
4312 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4313 "expected 6-bit unsigned immediate");
4314 case Match_UImm5_Lsl2:
4315 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4316 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004317 case Match_UImmRange2_64:
4318 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4319 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004320 case Match_UImm6_0:
4321 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4322 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004323 case Match_UImm6_Lsl2:
4324 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4325 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004326 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004327 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4328 "expected 6-bit signed immediate");
4329 case Match_UImm7_0:
4330 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4331 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004332 case Match_UImm7_N1:
4333 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4334 "expected immediate in range -1 .. 126");
4335 case Match_SImm7_Lsl2:
4336 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4337 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004338 case Match_UImm8_0:
4339 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4340 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004341 case Match_UImm10_0:
4342 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4343 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004344 case Match_SImm10_0:
4345 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4346 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004347 case Match_SImm11_0:
4348 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4349 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004350 case Match_UImm16:
4351 case Match_UImm16_Relaxed:
4352 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4353 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004354 case Match_SImm16:
4355 case Match_SImm16_Relaxed:
4356 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4357 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004358 case Match_SImm19_Lsl2:
4359 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4360 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004361 case Match_UImm20_0:
4362 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4363 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004364 case Match_UImm26_0:
4365 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4366 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004367 case Match_SImm32:
4368 case Match_SImm32_Relaxed:
4369 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4370 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004371 case Match_UImm32_Coerced:
4372 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4373 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004374 case Match_MemSImm9:
4375 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4376 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004377 case Match_MemSImm10:
4378 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4379 "expected memory with 10-bit signed offset");
4380 case Match_MemSImm10Lsl1:
4381 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4382 "expected memory with 11-bit signed offset and multiple of 2");
4383 case Match_MemSImm10Lsl2:
4384 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4385 "expected memory with 12-bit signed offset and multiple of 4");
4386 case Match_MemSImm10Lsl3:
4387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4388 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004389 case Match_MemSImm11:
4390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4391 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004392 case Match_MemSImm12:
4393 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4394 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004395 case Match_MemSImm16:
4396 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4397 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004398 }
Craig Topper589ceee2015-01-03 08:16:34 +00004399
4400 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004401}
4402
Toma Tabacud9d344b2015-04-27 14:05:04 +00004403void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4404 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4405 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4406 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004407}
4408
Toma Tabacu81496c12015-05-20 08:54:45 +00004409void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4410 if (!AssemblerOptions.back()->isMacro())
4411 Warning(Loc, "macro instruction expanded into multiple instructions");
4412}
4413
Daniel Sandersef638fe2014-10-03 15:37:37 +00004414void
4415MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4416 SMRange Range, bool ShowColors) {
4417 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004418 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004419 ShowColors);
4420}
4421
Jack Carter1ac53222013-02-20 23:11:17 +00004422int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004423 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004424
Vladimir Medic4c299852013-11-06 11:27:05 +00004425 CC = StringSwitch<unsigned>(Name)
4426 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004427 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004428 .Case("a0", 4)
4429 .Case("a1", 5)
4430 .Case("a2", 6)
4431 .Case("a3", 7)
4432 .Case("v0", 2)
4433 .Case("v1", 3)
4434 .Case("s0", 16)
4435 .Case("s1", 17)
4436 .Case("s2", 18)
4437 .Case("s3", 19)
4438 .Case("s4", 20)
4439 .Case("s5", 21)
4440 .Case("s6", 22)
4441 .Case("s7", 23)
4442 .Case("k0", 26)
4443 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004444 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004445 .Case("sp", 29)
4446 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004447 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004448 .Case("ra", 31)
4449 .Case("t0", 8)
4450 .Case("t1", 9)
4451 .Case("t2", 10)
4452 .Case("t3", 11)
4453 .Case("t4", 12)
4454 .Case("t5", 13)
4455 .Case("t6", 14)
4456 .Case("t7", 15)
4457 .Case("t8", 24)
4458 .Case("t9", 25)
4459 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004460
Toma Tabacufda445c2014-09-15 15:33:01 +00004461 if (!(isABI_N32() || isABI_N64()))
4462 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004463
Daniel Sandersef638fe2014-10-03 15:37:37 +00004464 if (12 <= CC && CC <= 15) {
4465 // Name is one of t4-t7
4466 AsmToken RegTok = getLexer().peekTok();
4467 SMRange RegRange = RegTok.getLocRange();
4468
4469 StringRef FixedName = StringSwitch<StringRef>(Name)
4470 .Case("t4", "t0")
4471 .Case("t5", "t1")
4472 .Case("t6", "t2")
4473 .Case("t7", "t3")
4474 .Default("");
4475 assert(FixedName != "" && "Register name is not one of t4-t7.");
4476
4477 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4478 "Did you mean $" + FixedName + "?", RegRange);
4479 }
4480
Toma Tabacufda445c2014-09-15 15:33:01 +00004481 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4482 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4483 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4484 if (8 <= CC && CC <= 11)
4485 CC += 4;
4486
4487 if (CC == -1)
4488 CC = StringSwitch<unsigned>(Name)
4489 .Case("a4", 8)
4490 .Case("a5", 9)
4491 .Case("a6", 10)
4492 .Case("a7", 11)
4493 .Case("kt0", 26)
4494 .Case("kt1", 27)
4495 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004496
4497 return CC;
4498}
Jack Carterd0bd6422013-04-18 00:41:53 +00004499
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004500int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4501 int CC;
4502
4503 CC = StringSwitch<unsigned>(Name)
4504 .Case("hwr_cpunum", 0)
4505 .Case("hwr_synci_step", 1)
4506 .Case("hwr_cc", 2)
4507 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004508 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004509 .Default(-1);
4510
4511 return CC;
4512}
4513
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004514int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00004515 if (Name[0] == 'f') {
4516 StringRef NumString = Name.substr(1);
4517 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004518 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004519 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004520 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004521 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004522 return IntVal;
4523 }
4524 return -1;
4525}
Jack Cartera63b16a2012-09-07 00:23:42 +00004526
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004527int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004528 if (Name.startswith("fcc")) {
4529 StringRef NumString = Name.substr(3);
4530 unsigned IntVal;
4531 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004532 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004533 if (IntVal > 7) // There are only 8 fcc registers.
4534 return -1;
4535 return IntVal;
4536 }
4537 return -1;
4538}
4539
4540int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004541 if (Name.startswith("ac")) {
4542 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004543 unsigned IntVal;
4544 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004545 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004546 if (IntVal > 3) // There are only 3 acc registers.
4547 return -1;
4548 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004549 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004550 return -1;
4551}
Jack Carterd0bd6422013-04-18 00:41:53 +00004552
Jack Carter5dc8ac92013-09-25 23:50:44 +00004553int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4554 unsigned IntVal;
4555
4556 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4557 return -1;
4558
4559 if (IntVal > 31)
4560 return -1;
4561
4562 return IntVal;
4563}
4564
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004565int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4566 int CC;
4567
4568 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004569 .Case("msair", 0)
4570 .Case("msacsr", 1)
4571 .Case("msaaccess", 2)
4572 .Case("msasave", 3)
4573 .Case("msamodify", 4)
4574 .Case("msarequest", 5)
4575 .Case("msamap", 6)
4576 .Case("msaunmap", 7)
4577 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004578
4579 return CC;
4580}
4581
Toma Tabacu89a712b2015-04-15 10:48:56 +00004582unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004583 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004584 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004585 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004586 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004587 return 0;
4588 }
4589 unsigned AT = getReg(
4590 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004591 return AT;
4592}
Jack Carter0b744b32012-10-04 02:29:46 +00004593
Jack Carterd0bd6422013-04-18 00:41:53 +00004594unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004595 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004596}
4597
Toma Tabacu13964452014-09-04 13:23:44 +00004598bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004599 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004600 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004601
Jack Carter30a59822012-10-04 04:03:53 +00004602 // Check if the current operand has a custom associated parser, if so, try to
4603 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004604 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4605 if (ResTy == MatchOperand_Success)
4606 return false;
4607 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4608 // there was a match, but an error occurred, in which case, just return that
4609 // the operand parsing failed.
4610 if (ResTy == MatchOperand_ParseFail)
4611 return true;
4612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004613 DEBUG(dbgs() << ".. Generic Parser\n");
4614
Jack Carterb4dbc172012-09-05 23:34:03 +00004615 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004616 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004617 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004618 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004619
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004620 // Almost all registers have been parsed by custom parsers. There is only
4621 // one exception to this. $zero (and it's alias $0) will reach this point
4622 // for div, divu, and similar instructions because it is not an operand
4623 // to the instruction definition but an explicit register. Special case
4624 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004625 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004626 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004627
Jack Carterd0bd6422013-04-18 00:41:53 +00004628 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004629 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004630 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004631 return true;
4632
Jack Carter873c7242013-01-12 01:03:14 +00004633 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004634 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004635 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004636 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004637 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004638
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004639 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004640 return false;
4641 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004642 default: {
4643 DEBUG(dbgs() << ".. generic integer expression\n");
4644
4645 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004646 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004647 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004648 return true;
4649
Jack Carter873c7242013-01-12 01:03:14 +00004650 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4651
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004652 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004653 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004654 }
Jack Carter0b744b32012-10-04 02:29:46 +00004655 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004656 return true;
4657}
4658
Jack Carterb5cf5902013-04-17 00:18:04 +00004659bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004660 switch (Expr->getKind()) {
4661 case MCExpr::Constant:
4662 return true;
4663 case MCExpr::SymbolRef:
4664 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4665 case MCExpr::Binary:
4666 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4667 if (!isEvaluated(BE->getLHS()))
4668 return false;
4669 return isEvaluated(BE->getRHS());
4670 }
4671 case MCExpr::Unary:
4672 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004673 case MCExpr::Target:
4674 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004675 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004676 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004677}
Jack Carterd0bd6422013-04-18 00:41:53 +00004678
Jack Carterb4dbc172012-09-05 23:34:03 +00004679bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4680 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004681 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004682 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004683 if (ResTy == MatchOperand_Success) {
4684 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004685 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004686 StartLoc = Operand.getStartLoc();
4687 EndLoc = Operand.getEndLoc();
4688
4689 // AFAIK, we only support numeric registers and named GPR's in CFI
4690 // directives.
4691 // Don't worry about eating tokens before failing. Using an unrecognised
4692 // register is a parse error.
4693 if (Operand.isGPRAsmReg()) {
4694 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004695 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004696 }
4697
4698 return (RegNo == (unsigned)-1);
4699 }
4700
4701 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004702 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004703}
4704
Jack Carterb5cf5902013-04-17 00:18:04 +00004705bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004706 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004707
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004708 if (isParenExpr)
4709 return getParser().parseParenExprOfDepth(0, Res, S);
4710 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004711}
4712
Alex Bradbury58eba092016-11-01 16:32:05 +00004713OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004714MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004715 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004716 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004717 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004718 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004719 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00004720 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004721 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004722 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004723
Jack Carterb5cf5902013-04-17 00:18:04 +00004724 if (getLexer().getKind() == AsmToken::LParen) {
4725 Parser.Lex();
4726 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004727 }
4728
Jack Carterb5cf5902013-04-17 00:18:04 +00004729 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004730 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004731 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004732
Jack Carterd0bd6422013-04-18 00:41:53 +00004733 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004734 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004735 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004736 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004737 SMLoc E =
4738 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004739 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004740 return MatchOperand_Success;
4741 }
4742 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004743 SMLoc E =
4744 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004745
Jack Carterd0bd6422013-04-18 00:41:53 +00004746 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004747 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004748 auto Base = MipsOperand::createGPRReg(
4749 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004750 Operands.push_back(
4751 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004752 return MatchOperand_Success;
4753 }
Simon Dardis858915f2016-10-18 15:17:17 +00004754 MCBinaryExpr::Opcode Opcode;
4755 // GAS and LLVM treat comparison operators different. GAS will generate -1
4756 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
4757 // highly unlikely to be found in a memory offset expression, we don't
4758 // handle them.
4759 switch (Tok.getKind()) {
4760 case AsmToken::Plus:
4761 Opcode = MCBinaryExpr::Add;
4762 Parser.Lex();
4763 break;
4764 case AsmToken::Minus:
4765 Opcode = MCBinaryExpr::Sub;
4766 Parser.Lex();
4767 break;
4768 case AsmToken::Star:
4769 Opcode = MCBinaryExpr::Mul;
4770 Parser.Lex();
4771 break;
4772 case AsmToken::Pipe:
4773 Opcode = MCBinaryExpr::Or;
4774 Parser.Lex();
4775 break;
4776 case AsmToken::Amp:
4777 Opcode = MCBinaryExpr::And;
4778 Parser.Lex();
4779 break;
4780 case AsmToken::LessLess:
4781 Opcode = MCBinaryExpr::Shl;
4782 Parser.Lex();
4783 break;
4784 case AsmToken::GreaterGreater:
4785 Opcode = MCBinaryExpr::LShr;
4786 Parser.Lex();
4787 break;
4788 case AsmToken::Caret:
4789 Opcode = MCBinaryExpr::Xor;
4790 Parser.Lex();
4791 break;
4792 case AsmToken::Slash:
4793 Opcode = MCBinaryExpr::Div;
4794 Parser.Lex();
4795 break;
4796 case AsmToken::Percent:
4797 Opcode = MCBinaryExpr::Mod;
4798 Parser.Lex();
4799 break;
4800 default:
4801 Error(Parser.getTok().getLoc(), "'(' or expression expected");
4802 return MatchOperand_ParseFail;
4803 }
4804 const MCExpr * NextExpr;
4805 if (getParser().parseExpression(NextExpr))
4806 return MatchOperand_ParseFail;
4807 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004808 }
4809
Jack Carterd0bd6422013-04-18 00:41:53 +00004810 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004811 }
4812
Toma Tabacu13964452014-09-04 13:23:44 +00004813 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004814 if (Res != MatchOperand_Success)
4815 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004816
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004817 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004818 Error(Parser.getTok().getLoc(), "')' expected");
4819 return MatchOperand_ParseFail;
4820 }
4821
Jack Carter873c7242013-01-12 01:03:14 +00004822 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4823
Jack Carterd0bd6422013-04-18 00:41:53 +00004824 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004825
Craig Topper062a2ba2014-04-25 05:30:21 +00004826 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004827 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004828
Jack Carterd0bd6422013-04-18 00:41:53 +00004829 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004830 std::unique_ptr<MipsOperand> op(
4831 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004832 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004833 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004834 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004835 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004836 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4837 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004838 if (IdVal->evaluateAsAbsolute(Imm))
4839 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004840 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004841 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004842 getContext());
4843 }
4844
David Blaikie960ea3f2014-06-08 16:18:35 +00004845 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004846 return MatchOperand_Success;
4847}
4848
David Blaikie960ea3f2014-06-08 16:18:35 +00004849bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004850 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004851 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004852 if (Sym) {
4853 SMLoc S = Parser.getTok().getLoc();
4854 const MCExpr *Expr;
4855 if (Sym->isVariable())
4856 Expr = Sym->getVariableValue();
4857 else
4858 return false;
4859 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004860 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004861 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004862 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004863 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004864 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004865 if (ResTy == MatchOperand_Success) {
4866 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004867 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004868 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004869 llvm_unreachable("Should never ParseFail");
4870 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004871 }
Jack Carterd76b2372013-03-21 21:44:16 +00004872 }
4873 }
4874 return false;
4875}
Jack Carterd0bd6422013-04-18 00:41:53 +00004876
Alex Bradbury58eba092016-11-01 16:32:05 +00004877OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004878MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004879 StringRef Identifier,
4880 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004881 int Index = matchCPURegisterName(Identifier);
4882 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004883 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004884 Index, Identifier, getContext().getRegisterInfo(), S,
4885 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004886 return MatchOperand_Success;
4887 }
4888
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004889 Index = matchHWRegsRegisterName(Identifier);
4890 if (Index != -1) {
4891 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004892 Index, Identifier, getContext().getRegisterInfo(), S,
4893 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004894 return MatchOperand_Success;
4895 }
4896
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004897 Index = matchFPURegisterName(Identifier);
4898 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004899 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004900 Index, Identifier, getContext().getRegisterInfo(), S,
4901 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004902 return MatchOperand_Success;
4903 }
4904
4905 Index = matchFCCRegisterName(Identifier);
4906 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004907 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004908 Index, Identifier, getContext().getRegisterInfo(), S,
4909 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004910 return MatchOperand_Success;
4911 }
4912
4913 Index = matchACRegisterName(Identifier);
4914 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004915 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004916 Index, Identifier, getContext().getRegisterInfo(), S,
4917 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004918 return MatchOperand_Success;
4919 }
4920
4921 Index = matchMSA128RegisterName(Identifier);
4922 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004923 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004924 Index, Identifier, getContext().getRegisterInfo(), S,
4925 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004926 return MatchOperand_Success;
4927 }
4928
4929 Index = matchMSA128CtrlRegisterName(Identifier);
4930 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004931 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004932 Index, Identifier, getContext().getRegisterInfo(), S,
4933 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004934 return MatchOperand_Success;
4935 }
4936
4937 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004938}
4939
Alex Bradbury58eba092016-11-01 16:32:05 +00004940OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004941MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004942 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004943 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004944
4945 if (Token.is(AsmToken::Identifier)) {
4946 DEBUG(dbgs() << ".. identifier\n");
4947 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004948 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004949 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004950 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004951 } else if (Token.is(AsmToken::Integer)) {
4952 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004953 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004954 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4955 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004956 return MatchOperand_Success;
4957 }
4958
4959 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4960
4961 return MatchOperand_NoMatch;
4962}
4963
Alex Bradbury58eba092016-11-01 16:32:05 +00004964OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004965MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004966 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004967 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004968
4969 auto Token = Parser.getTok();
4970
4971 SMLoc S = Token.getLoc();
4972
4973 if (Token.isNot(AsmToken::Dollar)) {
4974 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4975 if (Token.is(AsmToken::Identifier)) {
4976 if (searchSymbolAlias(Operands))
4977 return MatchOperand_Success;
4978 }
4979 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4980 return MatchOperand_NoMatch;
4981 }
4982 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004983
Toma Tabacu13964452014-09-04 13:23:44 +00004984 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004985 if (ResTy == MatchOperand_Success) {
4986 Parser.Lex(); // $
4987 Parser.Lex(); // identifier
4988 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004989 return ResTy;
4990}
4991
Alex Bradbury58eba092016-11-01 16:32:05 +00004992OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004993MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004994 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004995 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004996
4997 SMLoc S = getLexer().getLoc();
4998
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004999 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005000 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005001 if (ResTy != MatchOperand_NoMatch)
5002 return ResTy;
5003
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005004 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005005 const MCExpr *Expr = nullptr;
5006 if (Parser.parseExpression(Expr)) {
5007 // We have no way of knowing if a symbol was consumed so we must ParseFail
5008 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005009 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005010 Operands.push_back(
5011 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005012 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005013}
5014
Alex Bradbury58eba092016-11-01 16:32:05 +00005015OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005016MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005017 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005018 const MCExpr *IdVal;
5019 // If the first token is '$' we may have register operand.
5020 if (Parser.getTok().is(AsmToken::Dollar))
5021 return MatchOperand_NoMatch;
5022 SMLoc S = Parser.getTok().getLoc();
5023 if (getParser().parseExpression(IdVal))
5024 return MatchOperand_ParseFail;
5025 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005026 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005027 int64_t Val = MCE->getValue();
5028 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5029 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005030 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005031 return MatchOperand_Success;
5032}
5033
Alex Bradbury58eba092016-11-01 16:32:05 +00005034OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005035MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5036 MCAsmParser &Parser = getParser();
5037 SmallVector<unsigned, 10> Regs;
5038 unsigned RegNo;
5039 unsigned PrevReg = Mips::NoRegister;
5040 bool RegRange = false;
5041 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5042
5043 if (Parser.getTok().isNot(AsmToken::Dollar))
5044 return MatchOperand_ParseFail;
5045
5046 SMLoc S = Parser.getTok().getLoc();
5047 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5048 SMLoc E = getLexer().getLoc();
5049 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5050 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5051 if (RegRange) {
5052 // Remove last register operand because registers from register range
5053 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005054 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5055 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005056 Regs.push_back(RegNo);
5057 } else {
5058 unsigned TmpReg = PrevReg + 1;
5059 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005060 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5061 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5062 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005063 Error(E, "invalid register operand");
5064 return MatchOperand_ParseFail;
5065 }
5066
5067 PrevReg = TmpReg;
5068 Regs.push_back(TmpReg++);
5069 }
5070 }
5071
5072 RegRange = false;
5073 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005074 if ((PrevReg == Mips::NoRegister) &&
5075 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5076 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005077 Error(E, "$16 or $31 expected");
5078 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005079 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5080 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5081 !isGP64bit()) ||
5082 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5083 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5084 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005085 Error(E, "invalid register operand");
5086 return MatchOperand_ParseFail;
5087 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005088 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5089 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5090 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005091 Error(E, "consecutive register numbers expected");
5092 return MatchOperand_ParseFail;
5093 }
5094
5095 Regs.push_back(RegNo);
5096 }
5097
5098 if (Parser.getTok().is(AsmToken::Minus))
5099 RegRange = true;
5100
5101 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5102 !Parser.getTok().isNot(AsmToken::Comma)) {
5103 Error(E, "',' or '-' expected");
5104 return MatchOperand_ParseFail;
5105 }
5106
5107 Lex(); // Consume comma or minus
5108 if (Parser.getTok().isNot(AsmToken::Dollar))
5109 break;
5110
5111 PrevReg = RegNo;
5112 }
5113
5114 SMLoc E = Parser.getTok().getLoc();
5115 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5116 parseMemOperand(Operands);
5117 return MatchOperand_Success;
5118}
5119
Alex Bradbury58eba092016-11-01 16:32:05 +00005120OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005121MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5122 MCAsmParser &Parser = getParser();
5123
5124 SMLoc S = Parser.getTok().getLoc();
5125 if (parseAnyRegister(Operands) != MatchOperand_Success)
5126 return MatchOperand_ParseFail;
5127
5128 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005129 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005130
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005131 Operands.pop_back();
5132 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005133 return MatchOperand_Success;
5134}
5135
Alex Bradbury58eba092016-11-01 16:32:05 +00005136OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005137MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5138 MCAsmParser &Parser = getParser();
5139 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5140 SmallVector<unsigned, 10> Regs;
5141
5142 if (Parser.getTok().isNot(AsmToken::Dollar))
5143 return MatchOperand_ParseFail;
5144
5145 SMLoc S = Parser.getTok().getLoc();
5146
5147 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5148 return MatchOperand_ParseFail;
5149
5150 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5151 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5152 Regs.push_back(RegNo);
5153
5154 SMLoc E = Parser.getTok().getLoc();
5155 if (Parser.getTok().isNot(AsmToken::Comma)) {
5156 Error(E, "',' expected");
5157 return MatchOperand_ParseFail;
5158 }
5159
5160 // Remove comma.
5161 Parser.Lex();
5162
5163 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5164 return MatchOperand_ParseFail;
5165
5166 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5167 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5168 Regs.push_back(RegNo);
5169
5170 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5171
5172 return MatchOperand_Success;
5173}
5174
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005175/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5176/// either this.
5177/// ::= '(', register, ')'
5178/// handle it before we iterate so we don't get tripped up by the lack of
5179/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005180bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005181 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005182 if (getLexer().is(AsmToken::LParen)) {
5183 Operands.push_back(
5184 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5185 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005186 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005187 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005188 return Error(Loc, "unexpected token in argument list");
5189 }
5190 if (Parser.getTok().isNot(AsmToken::RParen)) {
5191 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005192 return Error(Loc, "unexpected token, expected ')'");
5193 }
5194 Operands.push_back(
5195 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5196 Parser.Lex();
5197 }
5198 return false;
5199}
5200
5201/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5202/// either one of these.
5203/// ::= '[', register, ']'
5204/// ::= '[', integer, ']'
5205/// handle it before we iterate so we don't get tripped up by the lack of
5206/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005207bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005208 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005209 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005210 if (getLexer().is(AsmToken::LBrac)) {
5211 Operands.push_back(
5212 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5213 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005214 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005215 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005216 return Error(Loc, "unexpected token in argument list");
5217 }
5218 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5219 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005220 return Error(Loc, "unexpected token, expected ']'");
5221 }
5222 Operands.push_back(
5223 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5224 Parser.Lex();
5225 }
5226 return false;
5227}
5228
David Blaikie960ea3f2014-06-08 16:18:35 +00005229bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5230 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005231 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005232 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005233
5234 // We have reached first instruction, module directive are now forbidden.
5235 getTargetStreamer().forbidModuleDirective();
5236
Vladimir Medic74593e62013-07-17 15:00:42 +00005237 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005238 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005239 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005240 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005241 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005242 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005243
5244 // Read the remaining operands.
5245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5246 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005247 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005248 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005249 return Error(Loc, "unexpected token in argument list");
5250 }
Toma Tabacu13964452014-09-04 13:23:44 +00005251 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005252 return true;
5253 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005254
Jack Carterd0bd6422013-04-18 00:41:53 +00005255 while (getLexer().is(AsmToken::Comma)) {
5256 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005257 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005258 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005259 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005260 return Error(Loc, "unexpected token in argument list");
5261 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005262 // Parse bracket and parenthesis suffixes before we iterate
5263 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005264 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005265 return true;
5266 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005267 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005268 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005269 }
5270 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005271 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5272 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005273 return Error(Loc, "unexpected token in argument list");
5274 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005275 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005276 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005277}
5278
Nirav Dave996fc132016-05-05 14:15:46 +00005279// FIXME: Given that these have the same name, these should both be
5280// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005281bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005282 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005283 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005284}
5285
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005286bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005287 return Error(Loc, ErrorMsg);
5288}
5289
Jack Carter0b744b32012-10-04 02:29:46 +00005290bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005291 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005292 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005293
5294 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005295 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005296
5297 Parser.Lex(); // Eat "noat".
5298
Jack Carterd0bd6422013-04-18 00:41:53 +00005299 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005300 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005301 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005302 return false;
5303 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005304
5305 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005306 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005307 return false;
5308}
Jack Carterd0bd6422013-04-18 00:41:53 +00005309
Jack Carter0b744b32012-10-04 02:29:46 +00005310bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005311 // Line can be: ".set at", which sets $at to $1
5312 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005313 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005314 Parser.Lex(); // Eat "at".
5315
Jack Carter0b744b32012-10-04 02:29:46 +00005316 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005317 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005318 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005319
5320 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005321 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005322 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005323 }
5324
5325 if (getLexer().isNot(AsmToken::Equal)) {
5326 reportParseError("unexpected token, expected equals sign");
5327 return false;
5328 }
5329 Parser.Lex(); // Eat "=".
5330
5331 if (getLexer().isNot(AsmToken::Dollar)) {
5332 if (getLexer().is(AsmToken::EndOfStatement)) {
5333 reportParseError("no register specified");
5334 return false;
5335 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005336 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005337 return false;
5338 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005339 }
5340 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005341
Toma Tabacu16a74492015-02-13 10:30:57 +00005342 // Find out what "reg" is.
5343 unsigned AtRegNo;
5344 const AsmToken &Reg = Parser.getTok();
5345 if (Reg.is(AsmToken::Identifier)) {
5346 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5347 } else if (Reg.is(AsmToken::Integer)) {
5348 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005349 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005350 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005351 return false;
5352 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005353
5354 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005355 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005356 reportParseError("invalid register");
5357 return false;
5358 }
5359 Parser.Lex(); // Eat "reg".
5360
5361 // If this is not the end of the statement, report an error.
5362 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5363 reportParseError("unexpected token, expected end of statement");
5364 return false;
5365 }
5366
5367 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5368
5369 Parser.Lex(); // Consume the EndOfStatement.
5370 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005371}
5372
5373bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005374 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005375 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005376 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005377 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005378 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005379 return false;
5380 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005381 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005382 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005383 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005384 return false;
5385}
5386
5387bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005388 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005389 Parser.Lex();
5390 // If this is not the end of the statement, report an error.
5391 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005392 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005393 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005394 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005395 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005396 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005397 Parser.Lex(); // Consume the EndOfStatement.
5398 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005399}
5400
5401bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005402 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005403 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005404 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005405 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005406 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005407 return false;
5408 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005409 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005410 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005411 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005412 return false;
5413}
5414
5415bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005416 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005417 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005418 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005420 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005421 return false;
5422 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005423 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005424 reportParseError("`noreorder' must be set before `nomacro'");
5425 return false;
5426 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005427 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005428 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005429 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005430 return false;
5431}
Jack Carterd76b2372013-03-21 21:44:16 +00005432
Daniel Sanders44934432014-08-07 12:03:36 +00005433bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005434 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005435 Parser.Lex();
5436
5437 // If this is not the end of the statement, report an error.
5438 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005439 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005440
5441 setFeatureBits(Mips::FeatureMSA, "msa");
5442 getTargetStreamer().emitDirectiveSetMsa();
5443 return false;
5444}
5445
5446bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005447 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005448 Parser.Lex();
5449
5450 // If this is not the end of the statement, report an error.
5451 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005452 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005453
5454 clearFeatureBits(Mips::FeatureMSA, "msa");
5455 getTargetStreamer().emitDirectiveSetNoMsa();
5456 return false;
5457}
5458
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005459bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005460 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005461 Parser.Lex(); // Eat "nodsp".
5462
5463 // If this is not the end of the statement, report an error.
5464 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5465 reportParseError("unexpected token, expected end of statement");
5466 return false;
5467 }
5468
5469 clearFeatureBits(Mips::FeatureDSP, "dsp");
5470 getTargetStreamer().emitDirectiveSetNoDsp();
5471 return false;
5472}
5473
Toma Tabacucc2502d2014-11-04 17:18:07 +00005474bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005475 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005476 Parser.Lex(); // Eat "mips16".
5477
Jack Carter39536722014-01-22 23:08:42 +00005478 // If this is not the end of the statement, report an error.
5479 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005480 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005481 return false;
5482 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005483
5484 setFeatureBits(Mips::FeatureMips16, "mips16");
5485 getTargetStreamer().emitDirectiveSetMips16();
5486 Parser.Lex(); // Consume the EndOfStatement.
5487 return false;
5488}
5489
5490bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005491 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005492 Parser.Lex(); // Eat "nomips16".
5493
5494 // If this is not the end of the statement, report an error.
5495 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5496 reportParseError("unexpected token, expected end of statement");
5497 return false;
5498 }
5499
5500 clearFeatureBits(Mips::FeatureMips16, "mips16");
5501 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005502 Parser.Lex(); // Consume the EndOfStatement.
5503 return false;
5504}
5505
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005506bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005507 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005508 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005509 // Line can be: .set fp=32
5510 // .set fp=xx
5511 // .set fp=64
5512 Parser.Lex(); // Eat fp token
5513 AsmToken Tok = Parser.getTok();
5514 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005515 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005516 return false;
5517 }
5518 Parser.Lex(); // Eat '=' token.
5519 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005520
5521 if (!parseFpABIValue(FpAbiVal, ".set"))
5522 return false;
5523
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005524 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005525 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005526 return false;
5527 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005528 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005529 Parser.Lex(); // Consume the EndOfStatement.
5530 return false;
5531}
5532
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005533bool MipsAsmParser::parseSetOddSPRegDirective() {
5534 MCAsmParser &Parser = getParser();
5535
5536 Parser.Lex(); // Eat "oddspreg".
5537 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5538 reportParseError("unexpected token, expected end of statement");
5539 return false;
5540 }
5541
5542 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5543 getTargetStreamer().emitDirectiveSetOddSPReg();
5544 return false;
5545}
5546
5547bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5548 MCAsmParser &Parser = getParser();
5549
5550 Parser.Lex(); // Eat "nooddspreg".
5551 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5552 reportParseError("unexpected token, expected end of statement");
5553 return false;
5554 }
5555
5556 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5557 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5558 return false;
5559}
5560
Toma Tabacu9db22db2014-09-09 10:15:38 +00005561bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005562 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005563 SMLoc Loc = getLexer().getLoc();
5564
5565 Parser.Lex();
5566 if (getLexer().isNot(AsmToken::EndOfStatement))
5567 return reportParseError("unexpected token, expected end of statement");
5568
5569 // Always keep an element on the options "stack" to prevent the user
5570 // from changing the initial options. This is how we remember them.
5571 if (AssemblerOptions.size() == 2)
5572 return reportParseError(Loc, ".set pop with no .set push");
5573
Akira Hatanakab11ef082015-11-14 06:35:56 +00005574 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005575 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005576 setAvailableFeatures(
5577 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5578 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005579
5580 getTargetStreamer().emitDirectiveSetPop();
5581 return false;
5582}
5583
5584bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005585 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005586 Parser.Lex();
5587 if (getLexer().isNot(AsmToken::EndOfStatement))
5588 return reportParseError("unexpected token, expected end of statement");
5589
5590 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005591 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005592 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005593
5594 getTargetStreamer().emitDirectiveSetPush();
5595 return false;
5596}
5597
Toma Tabacu29696502015-06-02 09:48:04 +00005598bool MipsAsmParser::parseSetSoftFloatDirective() {
5599 MCAsmParser &Parser = getParser();
5600 Parser.Lex();
5601 if (getLexer().isNot(AsmToken::EndOfStatement))
5602 return reportParseError("unexpected token, expected end of statement");
5603
5604 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5605 getTargetStreamer().emitDirectiveSetSoftFloat();
5606 return false;
5607}
5608
5609bool MipsAsmParser::parseSetHardFloatDirective() {
5610 MCAsmParser &Parser = getParser();
5611 Parser.Lex();
5612 if (getLexer().isNot(AsmToken::EndOfStatement))
5613 return reportParseError("unexpected token, expected end of statement");
5614
5615 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5616 getTargetStreamer().emitDirectiveSetHardFloat();
5617 return false;
5618}
5619
Jack Carterd76b2372013-03-21 21:44:16 +00005620bool MipsAsmParser::parseSetAssignment() {
5621 StringRef Name;
5622 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005623 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005624
5625 if (Parser.parseIdentifier(Name))
5626 reportParseError("expected identifier after .set");
5627
5628 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005629 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005630 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005631
Jack Carter3b2c96e2014-01-22 23:31:38 +00005632 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005633 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005634
Jim Grosbach6f482002015-05-18 18:43:14 +00005635 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005636 Sym->setVariableValue(Value);
5637
5638 return false;
5639}
Jack Carterd0bd6422013-04-18 00:41:53 +00005640
Toma Tabacu26647792014-09-09 12:52:14 +00005641bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005642 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005643 Parser.Lex();
5644 if (getLexer().isNot(AsmToken::EndOfStatement))
5645 return reportParseError("unexpected token, expected end of statement");
5646
5647 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005648 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005649 setAvailableFeatures(
5650 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5651 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005652 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5653
5654 getTargetStreamer().emitDirectiveSetMips0();
5655 return false;
5656}
5657
Toma Tabacu85618b32014-08-19 14:22:52 +00005658bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005659 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005660 Parser.Lex();
5661 if (getLexer().isNot(AsmToken::Equal))
5662 return reportParseError("unexpected token, expected equals sign");
5663
5664 Parser.Lex();
5665 StringRef Arch;
5666 if (Parser.parseIdentifier(Arch))
5667 return reportParseError("expected arch identifier");
5668
5669 StringRef ArchFeatureName =
5670 StringSwitch<StringRef>(Arch)
5671 .Case("mips1", "mips1")
5672 .Case("mips2", "mips2")
5673 .Case("mips3", "mips3")
5674 .Case("mips4", "mips4")
5675 .Case("mips5", "mips5")
5676 .Case("mips32", "mips32")
5677 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005678 .Case("mips32r3", "mips32r3")
5679 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005680 .Case("mips32r6", "mips32r6")
5681 .Case("mips64", "mips64")
5682 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005683 .Case("mips64r3", "mips64r3")
5684 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005685 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005686 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005687 .Case("r4000", "mips3") // This is an implementation of Mips3.
5688 .Default("");
5689
5690 if (ArchFeatureName.empty())
5691 return reportParseError("unsupported architecture");
5692
5693 selectArch(ArchFeatureName);
5694 getTargetStreamer().emitDirectiveSetArch(Arch);
5695 return false;
5696}
5697
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005698bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005699 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005700 Parser.Lex();
5701 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005702 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005703
Matheus Almeida2852af82014-04-22 10:15:54 +00005704 switch (Feature) {
5705 default:
5706 llvm_unreachable("Unimplemented feature");
5707 case Mips::FeatureDSP:
5708 setFeatureBits(Mips::FeatureDSP, "dsp");
5709 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005710 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005711 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005712 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005713 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005714 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005715 case Mips::FeatureMips1:
5716 selectArch("mips1");
5717 getTargetStreamer().emitDirectiveSetMips1();
5718 break;
5719 case Mips::FeatureMips2:
5720 selectArch("mips2");
5721 getTargetStreamer().emitDirectiveSetMips2();
5722 break;
5723 case Mips::FeatureMips3:
5724 selectArch("mips3");
5725 getTargetStreamer().emitDirectiveSetMips3();
5726 break;
5727 case Mips::FeatureMips4:
5728 selectArch("mips4");
5729 getTargetStreamer().emitDirectiveSetMips4();
5730 break;
5731 case Mips::FeatureMips5:
5732 selectArch("mips5");
5733 getTargetStreamer().emitDirectiveSetMips5();
5734 break;
5735 case Mips::FeatureMips32:
5736 selectArch("mips32");
5737 getTargetStreamer().emitDirectiveSetMips32();
5738 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005739 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005740 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005741 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005742 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005743 case Mips::FeatureMips32r3:
5744 selectArch("mips32r3");
5745 getTargetStreamer().emitDirectiveSetMips32R3();
5746 break;
5747 case Mips::FeatureMips32r5:
5748 selectArch("mips32r5");
5749 getTargetStreamer().emitDirectiveSetMips32R5();
5750 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005751 case Mips::FeatureMips32r6:
5752 selectArch("mips32r6");
5753 getTargetStreamer().emitDirectiveSetMips32R6();
5754 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005755 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005756 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005757 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005758 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005759 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005760 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005761 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005762 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005763 case Mips::FeatureMips64r3:
5764 selectArch("mips64r3");
5765 getTargetStreamer().emitDirectiveSetMips64R3();
5766 break;
5767 case Mips::FeatureMips64r5:
5768 selectArch("mips64r5");
5769 getTargetStreamer().emitDirectiveSetMips64R5();
5770 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005771 case Mips::FeatureMips64r6:
5772 selectArch("mips64r6");
5773 getTargetStreamer().emitDirectiveSetMips64R6();
5774 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005775 }
5776 return false;
5777}
5778
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005779bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005780 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005781 if (getLexer().isNot(AsmToken::Comma)) {
5782 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005783 return Error(Loc, ErrorStr);
5784 }
5785
Matheus Almeida2852af82014-04-22 10:15:54 +00005786 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005787 return true;
5788}
5789
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005790// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5791// In this class, it is only used for .cprestore.
5792// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5793// MipsTargetELFStreamer and MipsAsmParser.
5794bool MipsAsmParser::isPicAndNotNxxAbi() {
5795 return inPicMode() && !(isABI_N32() || isABI_N64());
5796}
5797
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005798bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005799 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005800 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005801
Toma Tabacudde4c462014-11-06 10:02:45 +00005802 if (inMips16Mode()) {
5803 reportParseError(".cpload is not supported in Mips16 mode");
5804 return false;
5805 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005806
David Blaikie960ea3f2014-06-08 16:18:35 +00005807 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005808 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005809 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5810 reportParseError("expected register containing function address");
5811 return false;
5812 }
5813
David Blaikie960ea3f2014-06-08 16:18:35 +00005814 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5815 if (!RegOpnd.isGPRAsmReg()) {
5816 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005817 return false;
5818 }
5819
Toma Tabacudde4c462014-11-06 10:02:45 +00005820 // If this is not the end of the statement, report an error.
5821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5822 reportParseError("unexpected token, expected end of statement");
5823 return false;
5824 }
5825
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005826 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005827 return false;
5828}
5829
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005830bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5831 MCAsmParser &Parser = getParser();
5832
5833 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5834 // is used in non-PIC mode.
5835
5836 if (inMips16Mode()) {
5837 reportParseError(".cprestore is not supported in Mips16 mode");
5838 return false;
5839 }
5840
5841 // Get the stack offset value.
5842 const MCExpr *StackOffset;
5843 int64_t StackOffsetVal;
5844 if (Parser.parseExpression(StackOffset)) {
5845 reportParseError("expected stack offset value");
5846 return false;
5847 }
5848
5849 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5850 reportParseError("stack offset is not an absolute expression");
5851 return false;
5852 }
5853
5854 if (StackOffsetVal < 0) {
5855 Warning(Loc, ".cprestore with negative stack offset has no effect");
5856 IsCpRestoreSet = false;
5857 } else {
5858 IsCpRestoreSet = true;
5859 CpRestoreOffset = StackOffsetVal;
5860 }
5861
5862 // If this is not the end of the statement, report an error.
5863 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5864 reportParseError("unexpected token, expected end of statement");
5865 return false;
5866 }
5867
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005868 if (!getTargetStreamer().emitDirectiveCpRestore(
5869 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005870 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005871 Parser.Lex(); // Consume the EndOfStatement.
5872 return false;
5873}
5874
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005875bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005876 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005877 unsigned FuncReg;
5878 unsigned Save;
5879 bool SaveIsReg = true;
5880
Matheus Almeida7e815762014-06-18 13:08:59 +00005881 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005882 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005883 if (ResTy == MatchOperand_NoMatch) {
5884 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005885 return false;
5886 }
5887
5888 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5889 if (!FuncRegOpnd.isGPRAsmReg()) {
5890 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005891 return false;
5892 }
5893
5894 FuncReg = FuncRegOpnd.getGPR32Reg();
5895 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005896
Toma Tabacu65f10572014-09-16 15:00:52 +00005897 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005898 return true;
5899
Toma Tabacu13964452014-09-04 13:23:44 +00005900 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005901 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005902 const MCExpr *OffsetExpr;
5903 int64_t OffsetVal;
5904 SMLoc ExprLoc = getLexer().getLoc();
5905
5906 if (Parser.parseExpression(OffsetExpr) ||
5907 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5908 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005909 return false;
5910 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005911
5912 Save = OffsetVal;
5913 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005914 } else {
5915 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5916 if (!SaveOpnd.isGPRAsmReg()) {
5917 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005918 return false;
5919 }
5920 Save = SaveOpnd.getGPR32Reg();
5921 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005922
Toma Tabacu65f10572014-09-16 15:00:52 +00005923 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005924 return true;
5925
Toma Tabacu8874eac2015-02-18 13:46:53 +00005926 const MCExpr *Expr;
5927 if (Parser.parseExpression(Expr)) {
5928 reportParseError("expected expression");
5929 return false;
5930 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005931
Toma Tabacu8874eac2015-02-18 13:46:53 +00005932 if (Expr->getKind() != MCExpr::SymbolRef) {
5933 reportParseError("expected symbol");
5934 return false;
5935 }
5936 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5937
Daniel Sandersf173dda2015-09-22 10:50:09 +00005938 CpSaveLocation = Save;
5939 CpSaveLocationIsRegister = SaveIsReg;
5940
Toma Tabacu8874eac2015-02-18 13:46:53 +00005941 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5942 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005943 return false;
5944}
5945
Daniel Sandersf173dda2015-09-22 10:50:09 +00005946bool MipsAsmParser::parseDirectiveCPReturn() {
5947 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5948 CpSaveLocationIsRegister);
5949 return false;
5950}
5951
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005952bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005953 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005954 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5955 const AsmToken &Tok = Parser.getTok();
5956
5957 if (Tok.getString() == "2008") {
5958 Parser.Lex();
5959 getTargetStreamer().emitDirectiveNaN2008();
5960 return false;
5961 } else if (Tok.getString() == "legacy") {
5962 Parser.Lex();
5963 getTargetStreamer().emitDirectiveNaNLegacy();
5964 return false;
5965 }
5966 }
5967 // If we don't recognize the option passed to the .nan
5968 // directive (e.g. no option or unknown option), emit an error.
5969 reportParseError("invalid option in .nan directive");
5970 return false;
5971}
5972
Jack Carter0b744b32012-10-04 02:29:46 +00005973bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005974 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005975 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005976 const AsmToken &Tok = Parser.getTok();
5977
5978 if (Tok.getString() == "noat") {
5979 return parseSetNoAtDirective();
5980 } else if (Tok.getString() == "at") {
5981 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005982 } else if (Tok.getString() == "arch") {
5983 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005984 } else if (Tok.getString() == "fp") {
5985 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005986 } else if (Tok.getString() == "oddspreg") {
5987 return parseSetOddSPRegDirective();
5988 } else if (Tok.getString() == "nooddspreg") {
5989 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005990 } else if (Tok.getString() == "pop") {
5991 return parseSetPopDirective();
5992 } else if (Tok.getString() == "push") {
5993 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005994 } else if (Tok.getString() == "reorder") {
5995 return parseSetReorderDirective();
5996 } else if (Tok.getString() == "noreorder") {
5997 return parseSetNoReorderDirective();
5998 } else if (Tok.getString() == "macro") {
5999 return parseSetMacroDirective();
6000 } else if (Tok.getString() == "nomacro") {
6001 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006002 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006003 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006004 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006005 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006006 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006007 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006008 getTargetStreamer().emitDirectiveSetNoMicroMips();
6009 Parser.eatToEndOfStatement();
6010 return false;
6011 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006012 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006013 } else if (Tok.getString() == "mips0") {
6014 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006015 } else if (Tok.getString() == "mips1") {
6016 return parseSetFeature(Mips::FeatureMips1);
6017 } else if (Tok.getString() == "mips2") {
6018 return parseSetFeature(Mips::FeatureMips2);
6019 } else if (Tok.getString() == "mips3") {
6020 return parseSetFeature(Mips::FeatureMips3);
6021 } else if (Tok.getString() == "mips4") {
6022 return parseSetFeature(Mips::FeatureMips4);
6023 } else if (Tok.getString() == "mips5") {
6024 return parseSetFeature(Mips::FeatureMips5);
6025 } else if (Tok.getString() == "mips32") {
6026 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006027 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006028 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006029 } else if (Tok.getString() == "mips32r3") {
6030 return parseSetFeature(Mips::FeatureMips32r3);
6031 } else if (Tok.getString() == "mips32r5") {
6032 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006033 } else if (Tok.getString() == "mips32r6") {
6034 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006035 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006036 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006037 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006038 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006039 } else if (Tok.getString() == "mips64r3") {
6040 return parseSetFeature(Mips::FeatureMips64r3);
6041 } else if (Tok.getString() == "mips64r5") {
6042 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006043 } else if (Tok.getString() == "mips64r6") {
6044 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006045 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006046 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006047 } else if (Tok.getString() == "nodsp") {
6048 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006049 } else if (Tok.getString() == "msa") {
6050 return parseSetMsaDirective();
6051 } else if (Tok.getString() == "nomsa") {
6052 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006053 } else if (Tok.getString() == "softfloat") {
6054 return parseSetSoftFloatDirective();
6055 } else if (Tok.getString() == "hardfloat") {
6056 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006057 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006058 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006059 parseSetAssignment();
6060 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006061 }
Jack Carter07c818d2013-01-25 01:31:34 +00006062
Jack Carter0b744b32012-10-04 02:29:46 +00006063 return true;
6064}
6065
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006066/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006067/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006068bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006069 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006070 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006071 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006072 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006073 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006074 return true;
6075
6076 getParser().getStreamer().EmitValue(Value, Size);
6077
6078 if (getLexer().is(AsmToken::EndOfStatement))
6079 break;
6080
Jack Carter07c818d2013-01-25 01:31:34 +00006081 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006082 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006083 Parser.Lex();
6084 }
6085 }
6086
6087 Parser.Lex();
6088 return false;
6089}
6090
Vladimir Medic4c299852013-11-06 11:27:05 +00006091/// parseDirectiveGpWord
6092/// ::= .gpword local_sym
6093bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006094 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006095 const MCExpr *Value;
6096 // EmitGPRel32Value requires an expression, so we are using base class
6097 // method to evaluate the expression.
6098 if (getParser().parseExpression(Value))
6099 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006100 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006101
Vladimir Medice10c1122013-11-13 13:18:04 +00006102 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006103 return Error(getLexer().getLoc(),
6104 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006105 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006106 return false;
6107}
6108
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006109/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006110/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006111bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006112 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006113 const MCExpr *Value;
6114 // EmitGPRel64Value requires an expression, so we are using base class
6115 // method to evaluate the expression.
6116 if (getParser().parseExpression(Value))
6117 return true;
6118 getParser().getStreamer().EmitGPRel64Value(Value);
6119
6120 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006121 return Error(getLexer().getLoc(),
6122 "unexpected token, expected end of statement");
6123 Parser.Lex(); // Eat EndOfStatement token.
6124 return false;
6125}
6126
6127/// parseDirectiveDtpRelWord
6128/// ::= .dtprelword tls_sym
6129bool MipsAsmParser::parseDirectiveDtpRelWord() {
6130 MCAsmParser &Parser = getParser();
6131 const MCExpr *Value;
6132 // EmitDTPRel32Value requires an expression, so we are using base class
6133 // method to evaluate the expression.
6134 if (getParser().parseExpression(Value))
6135 return true;
6136 getParser().getStreamer().EmitDTPRel32Value(Value);
6137
6138 if (getLexer().isNot(AsmToken::EndOfStatement))
6139 return Error(getLexer().getLoc(),
6140 "unexpected token, expected end of statement");
6141 Parser.Lex(); // Eat EndOfStatement token.
6142 return false;
6143}
6144
6145/// parseDirectiveDtpRelDWord
6146/// ::= .dtpreldword tls_sym
6147bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6148 MCAsmParser &Parser = getParser();
6149 const MCExpr *Value;
6150 // EmitDTPRel64Value requires an expression, so we are using base class
6151 // method to evaluate the expression.
6152 if (getParser().parseExpression(Value))
6153 return true;
6154 getParser().getStreamer().EmitDTPRel64Value(Value);
6155
6156 if (getLexer().isNot(AsmToken::EndOfStatement))
6157 return Error(getLexer().getLoc(),
6158 "unexpected token, expected end of statement");
6159 Parser.Lex(); // Eat EndOfStatement token.
6160 return false;
6161}
6162
6163/// parseDirectiveTpRelWord
6164/// ::= .tprelword tls_sym
6165bool MipsAsmParser::parseDirectiveTpRelWord() {
6166 MCAsmParser &Parser = getParser();
6167 const MCExpr *Value;
6168 // EmitTPRel32Value requires an expression, so we are using base class
6169 // method to evaluate the expression.
6170 if (getParser().parseExpression(Value))
6171 return true;
6172 getParser().getStreamer().EmitTPRel32Value(Value);
6173
6174 if (getLexer().isNot(AsmToken::EndOfStatement))
6175 return Error(getLexer().getLoc(),
6176 "unexpected token, expected end of statement");
6177 Parser.Lex(); // Eat EndOfStatement token.
6178 return false;
6179}
6180
6181/// parseDirectiveTpRelDWord
6182/// ::= .tpreldword tls_sym
6183bool MipsAsmParser::parseDirectiveTpRelDWord() {
6184 MCAsmParser &Parser = getParser();
6185 const MCExpr *Value;
6186 // EmitTPRel64Value requires an expression, so we are using base class
6187 // method to evaluate the expression.
6188 if (getParser().parseExpression(Value))
6189 return true;
6190 getParser().getStreamer().EmitTPRel64Value(Value);
6191
6192 if (getLexer().isNot(AsmToken::EndOfStatement))
6193 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006194 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006195 Parser.Lex(); // Eat EndOfStatement token.
6196 return false;
6197}
6198
Jack Carter0cd3c192014-01-06 23:27:31 +00006199bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006200 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006201 // Get the option token.
6202 AsmToken Tok = Parser.getTok();
6203 // At the moment only identifiers are supported.
6204 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006205 return Error(Parser.getTok().getLoc(),
6206 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006207 }
6208
6209 StringRef Option = Tok.getIdentifier();
6210
6211 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006212 // MipsAsmParser needs to know if the current PIC mode changes.
6213 IsPicEnabled = false;
6214
Jack Carter0cd3c192014-01-06 23:27:31 +00006215 getTargetStreamer().emitDirectiveOptionPic0();
6216 Parser.Lex();
6217 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006218 return Error(Parser.getTok().getLoc(),
6219 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006220 }
6221 return false;
6222 }
6223
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006224 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006225 // MipsAsmParser needs to know if the current PIC mode changes.
6226 IsPicEnabled = true;
6227
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006228 getTargetStreamer().emitDirectiveOptionPic2();
6229 Parser.Lex();
6230 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006231 return Error(Parser.getTok().getLoc(),
6232 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006233 }
6234 return false;
6235 }
6236
Jack Carter0cd3c192014-01-06 23:27:31 +00006237 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006238 Warning(Parser.getTok().getLoc(),
6239 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006240 Parser.eatToEndOfStatement();
6241 return false;
6242}
6243
Toma Tabacu9ca50962015-04-16 09:53:47 +00006244/// parseInsnDirective
6245/// ::= .insn
6246bool MipsAsmParser::parseInsnDirective() {
6247 // If this is not the end of the statement, report an error.
6248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6249 reportParseError("unexpected token, expected end of statement");
6250 return false;
6251 }
6252
6253 // The actual label marking happens in
6254 // MipsELFStreamer::createPendingLabelRelocs().
6255 getTargetStreamer().emitDirectiveInsn();
6256
6257 getParser().Lex(); // Eat EndOfStatement token.
6258 return false;
6259}
6260
Simon Atanasyanbe186202016-02-11 06:45:54 +00006261/// parseSSectionDirective
6262/// ::= .sbss
6263/// ::= .sdata
6264bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6265 // If this is not the end of the statement, report an error.
6266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6267 reportParseError("unexpected token, expected end of statement");
6268 return false;
6269 }
6270
6271 MCSection *ELFSection = getContext().getELFSection(
6272 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6273 getParser().getStreamer().SwitchSection(ELFSection);
6274
6275 getParser().Lex(); // Eat EndOfStatement token.
6276 return false;
6277}
6278
Daniel Sanders7e527422014-07-10 13:38:23 +00006279/// parseDirectiveModule
6280/// ::= .module oddspreg
6281/// ::= .module nooddspreg
6282/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006283/// ::= .module softfloat
6284/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006285bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006286 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006287 MCAsmLexer &Lexer = getLexer();
6288 SMLoc L = Lexer.getLoc();
6289
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006290 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006291 // TODO : get a better message.
6292 reportParseError(".module directive must appear before any code");
6293 return false;
6294 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006295
Toma Tabacuc405c822015-01-23 10:40:19 +00006296 StringRef Option;
6297 if (Parser.parseIdentifier(Option)) {
6298 reportParseError("expected .module option identifier");
6299 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006300 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006301
Toma Tabacuc405c822015-01-23 10:40:19 +00006302 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006303 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006304
Toma Tabacu3c499582015-06-25 10:56:57 +00006305 // Synchronize the abiflags information with the FeatureBits information we
6306 // changed above.
6307 getTargetStreamer().updateABIInfo(*this);
6308
6309 // If printing assembly, use the recently updated abiflags information.
6310 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6311 // emitted at the end).
6312 getTargetStreamer().emitDirectiveModuleOddSPReg();
6313
Toma Tabacuc405c822015-01-23 10:40:19 +00006314 // If this is not the end of the statement, report an error.
6315 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6316 reportParseError("unexpected token, expected end of statement");
6317 return false;
6318 }
6319
6320 return false; // parseDirectiveModule has finished successfully.
6321 } else if (Option == "nooddspreg") {
6322 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006323 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006324 }
6325
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006326 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006327
Toma Tabacu3c499582015-06-25 10:56:57 +00006328 // Synchronize the abiflags information with the FeatureBits information we
6329 // changed above.
6330 getTargetStreamer().updateABIInfo(*this);
6331
6332 // If printing assembly, use the recently updated abiflags information.
6333 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6334 // emitted at the end).
6335 getTargetStreamer().emitDirectiveModuleOddSPReg();
6336
Toma Tabacuc405c822015-01-23 10:40:19 +00006337 // If this is not the end of the statement, report an error.
6338 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6339 reportParseError("unexpected token, expected end of statement");
6340 return false;
6341 }
6342
6343 return false; // parseDirectiveModule has finished successfully.
6344 } else if (Option == "fp") {
6345 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006346 } else if (Option == "softfloat") {
6347 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6348
6349 // Synchronize the ABI Flags information with the FeatureBits information we
6350 // updated above.
6351 getTargetStreamer().updateABIInfo(*this);
6352
6353 // If printing assembly, use the recently updated ABI Flags information.
6354 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6355 // emitted later).
6356 getTargetStreamer().emitDirectiveModuleSoftFloat();
6357
6358 // If this is not the end of the statement, report an error.
6359 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6360 reportParseError("unexpected token, expected end of statement");
6361 return false;
6362 }
6363
6364 return false; // parseDirectiveModule has finished successfully.
6365 } else if (Option == "hardfloat") {
6366 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6367
6368 // Synchronize the ABI Flags information with the FeatureBits information we
6369 // updated above.
6370 getTargetStreamer().updateABIInfo(*this);
6371
6372 // If printing assembly, use the recently updated ABI Flags information.
6373 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6374 // emitted later).
6375 getTargetStreamer().emitDirectiveModuleHardFloat();
6376
6377 // If this is not the end of the statement, report an error.
6378 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6379 reportParseError("unexpected token, expected end of statement");
6380 return false;
6381 }
6382
6383 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006384 } else {
6385 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6386 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006387}
6388
6389/// parseDirectiveModuleFP
6390/// ::= =32
6391/// ::= =xx
6392/// ::= =64
6393bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006394 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006395 MCAsmLexer &Lexer = getLexer();
6396
6397 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006398 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006399 return false;
6400 }
6401 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006402
Daniel Sanders7e527422014-07-10 13:38:23 +00006403 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006404 if (!parseFpABIValue(FpABI, ".module"))
6405 return false;
6406
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006408 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006409 return false;
6410 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006411
Toma Tabacua64e5402015-06-25 12:44:38 +00006412 // Synchronize the abiflags information with the FeatureBits information we
6413 // changed above.
6414 getTargetStreamer().updateABIInfo(*this);
6415
6416 // If printing assembly, use the recently updated abiflags information.
6417 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6418 // emitted at the end).
6419 getTargetStreamer().emitDirectiveModuleFP();
6420
Daniel Sanders7e527422014-07-10 13:38:23 +00006421 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006422 return false;
6423}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006424
Daniel Sanders7e527422014-07-10 13:38:23 +00006425bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006426 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006427 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006428 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006429 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006430
6431 if (Lexer.is(AsmToken::Identifier)) {
6432 StringRef Value = Parser.getTok().getString();
6433 Parser.Lex();
6434
6435 if (Value != "xx") {
6436 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6437 return false;
6438 }
6439
6440 if (!isABI_O32()) {
6441 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6442 return false;
6443 }
6444
Daniel Sanders7e527422014-07-10 13:38:23 +00006445 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006446 if (ModuleLevelOptions) {
6447 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6448 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6449 } else {
6450 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6451 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6452 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006453 return true;
6454 }
6455
6456 if (Lexer.is(AsmToken::Integer)) {
6457 unsigned Value = Parser.getTok().getIntVal();
6458 Parser.Lex();
6459
6460 if (Value != 32 && Value != 64) {
6461 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6462 return false;
6463 }
6464
6465 if (Value == 32) {
6466 if (!isABI_O32()) {
6467 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6468 return false;
6469 }
6470
Daniel Sanders7e527422014-07-10 13:38:23 +00006471 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006472 if (ModuleLevelOptions) {
6473 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6474 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6475 } else {
6476 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6477 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6478 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006479 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006480 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006481 if (ModuleLevelOptions) {
6482 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6483 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6484 } else {
6485 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6486 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6487 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006488 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006489
Daniel Sanders7e527422014-07-10 13:38:23 +00006490 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006491 }
6492
6493 return false;
6494}
6495
Jack Carter0b744b32012-10-04 02:29:46 +00006496bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006497 // This returns false if this function recognizes the directive
6498 // regardless of whether it is successfully handles or reports an
6499 // error. Otherwise it returns true to give the generic parser a
6500 // chance at recognizing it.
6501
Rafael Espindola961d4692014-11-11 05:18:41 +00006502 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006503 StringRef IDVal = DirectiveID.getString();
6504
Nirav Dave996fc132016-05-05 14:15:46 +00006505 if (IDVal == ".cpload") {
6506 parseDirectiveCpLoad(DirectiveID.getLoc());
6507 return false;
6508 }
6509 if (IDVal == ".cprestore") {
6510 parseDirectiveCpRestore(DirectiveID.getLoc());
6511 return false;
6512 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006513 if (IDVal == ".dword") {
6514 parseDataDirective(8, DirectiveID.getLoc());
6515 return false;
6516 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006517 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006518 StringRef SymbolName;
6519
6520 if (Parser.parseIdentifier(SymbolName)) {
6521 reportParseError("expected identifier after .ent");
6522 return false;
6523 }
6524
6525 // There's an undocumented extension that allows an integer to
6526 // follow the name of the procedure which AFAICS is ignored by GAS.
6527 // Example: .ent foo,2
6528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6529 if (getLexer().isNot(AsmToken::Comma)) {
6530 // Even though we accept this undocumented extension for compatibility
6531 // reasons, the additional integer argument does not actually change
6532 // the behaviour of the '.ent' directive, so we would like to discourage
6533 // its use. We do this by not referring to the extended version in
6534 // error messages which are not directly related to its use.
6535 reportParseError("unexpected token, expected end of statement");
6536 return false;
6537 }
6538 Parser.Lex(); // Eat the comma.
6539 const MCExpr *DummyNumber;
6540 int64_t DummyNumberVal;
6541 // If the user was explicitly trying to use the extended version,
6542 // we still give helpful extension-related error messages.
6543 if (Parser.parseExpression(DummyNumber)) {
6544 reportParseError("expected number after comma");
6545 return false;
6546 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006547 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006548 reportParseError("expected an absolute expression after comma");
6549 return false;
6550 }
6551 }
6552
6553 // If this is not the end of the statement, report an error.
6554 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6555 reportParseError("unexpected token, expected end of statement");
6556 return false;
6557 }
6558
Jim Grosbach6f482002015-05-18 18:43:14 +00006559 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006560
6561 getTargetStreamer().emitDirectiveEnt(*Sym);
6562 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006563 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006564 return false;
6565 }
6566
Jack Carter07c818d2013-01-25 01:31:34 +00006567 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006568 StringRef SymbolName;
6569
6570 if (Parser.parseIdentifier(SymbolName)) {
6571 reportParseError("expected identifier after .end");
6572 return false;
6573 }
6574
6575 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6576 reportParseError("unexpected token, expected end of statement");
6577 return false;
6578 }
6579
6580 if (CurrentFn == nullptr) {
6581 reportParseError(".end used without .ent");
6582 return false;
6583 }
6584
6585 if ((SymbolName != CurrentFn->getName())) {
6586 reportParseError(".end symbol does not match .ent symbol");
6587 return false;
6588 }
6589
6590 getTargetStreamer().emitDirectiveEnd(SymbolName);
6591 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006592 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006593 return false;
6594 }
6595
Jack Carter07c818d2013-01-25 01:31:34 +00006596 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006597 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6598 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006599 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006600 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6601 reportParseError("expected stack register");
6602 return false;
6603 }
6604
6605 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6606 if (!StackRegOpnd.isGPRAsmReg()) {
6607 reportParseError(StackRegOpnd.getStartLoc(),
6608 "expected general purpose register");
6609 return false;
6610 }
6611 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6612
6613 if (Parser.getTok().is(AsmToken::Comma))
6614 Parser.Lex();
6615 else {
6616 reportParseError("unexpected token, expected comma");
6617 return false;
6618 }
6619
6620 // Parse the frame size.
6621 const MCExpr *FrameSize;
6622 int64_t FrameSizeVal;
6623
6624 if (Parser.parseExpression(FrameSize)) {
6625 reportParseError("expected frame size value");
6626 return false;
6627 }
6628
Jim Grosbach13760bd2015-05-30 01:25:56 +00006629 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006630 reportParseError("frame size not an absolute expression");
6631 return false;
6632 }
6633
6634 if (Parser.getTok().is(AsmToken::Comma))
6635 Parser.Lex();
6636 else {
6637 reportParseError("unexpected token, expected comma");
6638 return false;
6639 }
6640
6641 // Parse the return register.
6642 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006643 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006644 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6645 reportParseError("expected return register");
6646 return false;
6647 }
6648
6649 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6650 if (!ReturnRegOpnd.isGPRAsmReg()) {
6651 reportParseError(ReturnRegOpnd.getStartLoc(),
6652 "expected general purpose register");
6653 return false;
6654 }
6655
6656 // If this is not the end of the statement, report an error.
6657 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6658 reportParseError("unexpected token, expected end of statement");
6659 return false;
6660 }
6661
6662 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6663 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006664 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006665 return false;
6666 }
6667
Jack Carter07c818d2013-01-25 01:31:34 +00006668 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006669 parseDirectiveSet();
6670 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006671 }
6672
Daniel Sandersd97a6342014-08-13 10:07:34 +00006673 if (IDVal == ".mask" || IDVal == ".fmask") {
6674 // .mask bitmask, frame_offset
6675 // bitmask: One bit for each register used.
6676 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6677 // first register is expected to be saved.
6678 // Examples:
6679 // .mask 0x80000000, -4
6680 // .fmask 0x80000000, -4
6681 //
Jack Carterbe332172012-09-07 00:48:02 +00006682
Daniel Sandersd97a6342014-08-13 10:07:34 +00006683 // Parse the bitmask
6684 const MCExpr *BitMask;
6685 int64_t BitMaskVal;
6686
6687 if (Parser.parseExpression(BitMask)) {
6688 reportParseError("expected bitmask value");
6689 return false;
6690 }
6691
Jim Grosbach13760bd2015-05-30 01:25:56 +00006692 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006693 reportParseError("bitmask not an absolute expression");
6694 return false;
6695 }
6696
6697 if (Parser.getTok().is(AsmToken::Comma))
6698 Parser.Lex();
6699 else {
6700 reportParseError("unexpected token, expected comma");
6701 return false;
6702 }
6703
6704 // Parse the frame_offset
6705 const MCExpr *FrameOffset;
6706 int64_t FrameOffsetVal;
6707
6708 if (Parser.parseExpression(FrameOffset)) {
6709 reportParseError("expected frame offset value");
6710 return false;
6711 }
6712
Jim Grosbach13760bd2015-05-30 01:25:56 +00006713 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006714 reportParseError("frame offset not an absolute expression");
6715 return false;
6716 }
6717
6718 // If this is not the end of the statement, report an error.
6719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6720 reportParseError("unexpected token, expected end of statement");
6721 return false;
6722 }
6723
6724 if (IDVal == ".mask")
6725 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6726 else
6727 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006728 return false;
6729 }
6730
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006731 if (IDVal == ".nan")
6732 return parseDirectiveNaN();
6733
Jack Carter07c818d2013-01-25 01:31:34 +00006734 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006735 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006736 return false;
6737 }
6738
Rafael Espindolab59fb732014-03-28 18:50:26 +00006739 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006740 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006741 return false;
6742 }
6743
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006744 if (IDVal == ".dtprelword") {
6745 parseDirectiveDtpRelWord();
6746 return false;
6747 }
6748
6749 if (IDVal == ".dtpreldword") {
6750 parseDirectiveDtpRelDWord();
6751 return false;
6752 }
6753
6754 if (IDVal == ".tprelword") {
6755 parseDirectiveTpRelWord();
6756 return false;
6757 }
6758
6759 if (IDVal == ".tpreldword") {
6760 parseDirectiveTpRelDWord();
6761 return false;
6762 }
6763
Jack Carter07c818d2013-01-25 01:31:34 +00006764 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006765 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006766 return false;
6767 }
6768
Scott Egertond1aeb052016-02-15 16:11:51 +00006769 if (IDVal == ".hword") {
6770 parseDataDirective(2, DirectiveID.getLoc());
6771 return false;
6772 }
6773
Nirav Dave996fc132016-05-05 14:15:46 +00006774 if (IDVal == ".option") {
6775 parseDirectiveOption();
6776 return false;
6777 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006778
6779 if (IDVal == ".abicalls") {
6780 getTargetStreamer().emitDirectiveAbiCalls();
6781 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006782 Error(Parser.getTok().getLoc(),
6783 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006784 }
6785 return false;
6786 }
6787
Nirav Dave996fc132016-05-05 14:15:46 +00006788 if (IDVal == ".cpsetup") {
6789 parseDirectiveCPSetup();
6790 return false;
6791 }
6792 if (IDVal == ".cpreturn") {
6793 parseDirectiveCPReturn();
6794 return false;
6795 }
6796 if (IDVal == ".module") {
6797 parseDirectiveModule();
6798 return false;
6799 }
6800 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6801 parseInternalDirectiveReallowModule();
6802 return false;
6803 }
6804 if (IDVal == ".insn") {
6805 parseInsnDirective();
6806 return false;
6807 }
6808 if (IDVal == ".sbss") {
6809 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6810 return false;
6811 }
6812 if (IDVal == ".sdata") {
6813 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6814 return false;
6815 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006816
Rafael Espindola870c4e92012-01-11 03:56:41 +00006817 return true;
6818}
6819
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006820bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6821 // If this is not the end of the statement, report an error.
6822 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6823 reportParseError("unexpected token, expected end of statement");
6824 return false;
6825 }
6826
6827 getTargetStreamer().reallowModuleDirective();
6828
6829 getParser().Lex(); // Eat EndOfStatement token.
6830 return false;
6831}
6832
Rafael Espindola870c4e92012-01-11 03:56:41 +00006833extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006834 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6835 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6836 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6837 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006838}
Jack Carterb4dbc172012-09-05 23:34:03 +00006839
6840#define GET_REGISTER_MATCHER
6841#define GET_MATCHER_IMPLEMENTATION
6842#include "MipsGenAsmMatcher.inc"