blob: 4db5e3c8cca5d7c7806c79069f7e45c5e5d4201c [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"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#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"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000307 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
308 const MCSubtargetInfo *STI);
309
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000310 bool reportParseError(Twine ErrorMsg);
311 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000312
Jack Carterb5cf5902013-04-17 00:18:04 +0000313 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000314
315 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000316 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000317 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000318 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000319 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000320 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000321 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000322 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000323 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000324 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000325 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000326 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000327 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000328 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000329 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000330
331 bool parseSetAtDirective();
332 bool parseSetNoAtDirective();
333 bool parseSetMacroDirective();
334 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000335 bool parseSetMsaDirective();
336 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000337 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000338 bool parseSetReorderDirective();
339 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000340 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000341 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000342 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000343 bool parseSetOddSPRegDirective();
344 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000345 bool parseSetPopDirective();
346 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000347 bool parseSetSoftFloatDirective();
348 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000349 bool parseSetMtDirective();
350 bool parseSetNoMtDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000351
Jack Carterd76b2372013-03-21 21:44:16 +0000352 bool parseSetAssignment();
353
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000354 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000355 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000356 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000357 bool parseDirectiveDtpRelWord();
358 bool parseDirectiveDtpRelDWord();
359 bool parseDirectiveTpRelWord();
360 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000361 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000362 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000363 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
364 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000365
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000366 bool parseInternalDirectiveReallowModule();
367
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000368 bool eatComma(StringRef ErrorStr);
369
Jack Carter1ac53222013-02-20 23:11:17 +0000370 int matchCPURegisterName(StringRef Symbol);
371
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000372 int matchHWRegsRegisterName(StringRef Symbol);
373
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000374 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000375
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000376 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000377
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000378 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000379
Jack Carter5dc8ac92013-09-25 23:50:44 +0000380 int matchMSA128RegisterName(StringRef Name);
381
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000382 int matchMSA128CtrlRegisterName(StringRef Name);
383
Jack Carterd0bd6422013-04-18 00:41:53 +0000384 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000385
Toma Tabacu89a712b2015-04-15 10:48:56 +0000386 /// Returns the internal register number for the current AT. Also checks if
387 /// the current AT is unavailable (set to $0) and gives an error if it is.
388 /// This should be used in pseudo-instruction expansions which need AT.
389 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000390
Simon Dardis3aa8a902017-02-06 12:43:46 +0000391 bool canUseATReg();
392
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000393 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
394 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000395
396 // Helper function that checks if the value of a vector index is within the
397 // boundaries of accepted values for each RegisterKind
398 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
399 bool validateMSAIndex(int Val, int RegKind);
400
Daniel Sandersf0df2212014-08-04 12:20:00 +0000401 // Selects a new architecture by updating the FeatureBits with the necessary
402 // info including implied dependencies.
403 // Internally, it clears all the feature bits related to *any* architecture
404 // and selects the new one using the ToggleFeature functionality of the
405 // MCSubtargetInfo object that handles implied dependencies. The reason we
406 // clear all the arch related bits manually is because ToggleFeature only
407 // clears the features that imply the feature being cleared and not the
408 // features implied by the feature being cleared. This is easier to see
409 // with an example:
410 // --------------------------------------------------
411 // | Feature | Implies |
412 // | -------------------------------------------------|
413 // | FeatureMips1 | None |
414 // | FeatureMips2 | FeatureMips1 |
415 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
416 // | FeatureMips4 | FeatureMips3 |
417 // | ... | |
418 // --------------------------------------------------
419 //
420 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
421 // FeatureMipsGP64 | FeatureMips1)
422 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
423 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000424 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000425 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000426 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
427 STI.setFeatureBits(FeatureBits);
428 setAvailableFeatures(
429 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000430 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000431 }
432
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000433 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000434 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000435 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000436 setAvailableFeatures(
437 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000438 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000439 }
440 }
441
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000442 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000443 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000444 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000445 setAvailableFeatures(
446 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000447 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000448 }
449 }
450
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000451 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
452 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000453 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000454 }
455
456 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
457 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000458 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000459 }
460
Rafael Espindola870c4e92012-01-11 03:56:41 +0000461public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000462 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000463 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000464 Match_RequiresDifferentOperands,
465 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000466 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000467 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000468 Match_NonZeroOperandForSync,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000469 Match_RequiresPosSizeRange0_32,
470 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000471 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000472#define GET_OPERAND_DIAGNOSTIC_TYPES
473#include "MipsGenAsmMatcher.inc"
474#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000475 };
476
Akira Hatanakab11ef082015-11-14 06:35:56 +0000477 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000478 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000479 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000480 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
481 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000482 MCAsmParserExtension::Initialize(parser);
483
Toma Tabacu11e14a92015-04-21 11:50:52 +0000484 parser.addAliasForDirective(".asciiz", ".asciz");
485
Jack Carterb4dbc172012-09-05 23:34:03 +0000486 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000488
Toma Tabacu9db22db2014-09-09 10:15:38 +0000489 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000490 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000491 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000492
Toma Tabacu9db22db2014-09-09 10:15:38 +0000493 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000494 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000496
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 getTargetStreamer().updateABIInfo(*this);
498
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000499 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000500 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000501
502 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000503
Rafael Espindola699281c2016-05-18 11:58:50 +0000504 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000505
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000506 IsCpRestoreSet = false;
507 CpRestoreOffset = -1;
508
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000509 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000510 if ((TheTriple.getArch() == Triple::mips) ||
511 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000512 IsLittleEndian = false;
513 else
514 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000515 }
516
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000517 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
518 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
519
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 bool isGP64bit() const {
521 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
522 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000523
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 bool isFP64bit() const {
525 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
526 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000527
Eric Christophera5762812015-01-26 17:33:46 +0000528 const MipsABIInfo &getABI() const { return ABI; }
529 bool isABI_N32() const { return ABI.IsN32(); }
530 bool isABI_N64() const { return ABI.IsN64(); }
531 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 bool isABI_FPXX() const {
533 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
534 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000535
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000536 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000537 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000538 }
539
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000540 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000541 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000542 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000543
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 bool hasMips1() const {
545 return getSTI().getFeatureBits()[Mips::FeatureMips1];
546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 bool hasMips2() const {
549 return getSTI().getFeatureBits()[Mips::FeatureMips2];
550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 bool hasMips3() const {
553 return getSTI().getFeatureBits()[Mips::FeatureMips3];
554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000556 bool hasMips4() const {
557 return getSTI().getFeatureBits()[Mips::FeatureMips4];
558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000560 bool hasMips5() const {
561 return getSTI().getFeatureBits()[Mips::FeatureMips5];
562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return getSTI().getFeatureBits()[Mips::FeatureMips32];
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 hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000571
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000572 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000573 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000576 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000577 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Daniel Sanders17793142015-02-18 16:24:50 +0000580 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000581 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Daniel Sanders17793142015-02-18 16:24:50 +0000584 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000585 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Daniel Sanders17793142015-02-18 16:24:50 +0000588 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000589 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000591
Daniel Sanders17793142015-02-18 16:24:50 +0000592 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000593 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000594 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000595
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000596 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000597 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000598 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000599
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000600 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000601 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000602 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000603
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 bool hasDSP() const {
605 return getSTI().getFeatureBits()[Mips::FeatureDSP];
606 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000607
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000608 bool hasDSPR2() const {
609 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
610 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000611
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000612 bool hasDSPR3() const {
613 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
614 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000615
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000616 bool hasMSA() const {
617 return getSTI().getFeatureBits()[Mips::FeatureMSA];
618 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000619
Kai Nackee0245392015-01-27 19:11:28 +0000620 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000621 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000622 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000623
Daniel Sandersa6994442015-08-18 12:33:54 +0000624 bool inPicMode() {
625 return IsPicEnabled;
626 }
627
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000628 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000629 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000630 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000631
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000632 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000633 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000634 }
635
Eric Christophere8ae3e32015-05-07 23:10:21 +0000636 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000637 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000638 }
Simon Dardisae719c52017-07-11 18:03:20 +0000639 bool hasMT() const {
640 return getSTI().getFeatureBits()[Mips::FeatureMT];
641 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000642
Toma Tabacud9d344b2015-04-27 14:05:04 +0000643 /// Warn if RegIndex is the same as the current AT.
644 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000645
646 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000647
648 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000649
650 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
651 AsmToken::TokenKind OperatorToken,
652 MCContext &Ctx) override {
653 switch(OperatorToken) {
654 default:
655 llvm_unreachable("Unknown token");
656 return nullptr;
657 case AsmToken::PercentCall16:
658 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
659 case AsmToken::PercentCall_Hi:
660 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
661 case AsmToken::PercentCall_Lo:
662 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
663 case AsmToken::PercentDtprel_Hi:
664 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
665 case AsmToken::PercentDtprel_Lo:
666 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
667 case AsmToken::PercentGot:
668 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
669 case AsmToken::PercentGot_Disp:
670 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
671 case AsmToken::PercentGot_Hi:
672 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
673 case AsmToken::PercentGot_Lo:
674 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
675 case AsmToken::PercentGot_Ofst:
676 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
677 case AsmToken::PercentGot_Page:
678 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
679 case AsmToken::PercentGottprel:
680 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
681 case AsmToken::PercentGp_Rel:
682 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
683 case AsmToken::PercentHi:
684 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
685 case AsmToken::PercentHigher:
686 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
687 case AsmToken::PercentHighest:
688 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
689 case AsmToken::PercentLo:
690 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
691 case AsmToken::PercentNeg:
692 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
693 case AsmToken::PercentPcrel_Hi:
694 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
695 case AsmToken::PercentPcrel_Lo:
696 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
697 case AsmToken::PercentTlsgd:
698 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
699 case AsmToken::PercentTlsldm:
700 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
701 case AsmToken::PercentTprel_Hi:
702 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
703 case AsmToken::PercentTprel_Lo:
704 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
705 }
706 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000707};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000708
709/// MipsOperand - Instances of this class represent a parsed Mips machine
710/// instruction.
711class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000712public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000713 /// Broad categories of register classes
714 /// The exact class is finalized by the render method.
715 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000716 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000717 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000718 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000719 RegKind_FCC = 4, /// FCC
720 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
721 RegKind_MSACtrl = 16, /// MSA control registers
722 RegKind_COP2 = 32, /// COP2
723 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
724 /// context).
725 RegKind_CCR = 128, /// CCR
726 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000727 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000728 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000729 /// Potentially any (e.g. $1)
730 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
731 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000732 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000733 };
734
735private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000736 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000737 k_Immediate, /// An immediate (possibly involving symbol references)
738 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000739 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000740 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000741 k_RegList, /// A physical register list
742 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000743 } Kind;
744
David Blaikie960ea3f2014-06-08 16:18:35 +0000745public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000746 MipsOperand(KindTy K, MipsAsmParser &Parser)
747 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
748
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000749 ~MipsOperand() override {
750 switch (Kind) {
751 case k_Immediate:
752 break;
753 case k_Memory:
754 delete Mem.Base;
755 break;
756 case k_RegList:
757 delete RegList.List;
758 case k_RegisterIndex:
759 case k_Token:
760 case k_RegPair:
761 break;
762 }
763 }
764
David Blaikie960ea3f2014-06-08 16:18:35 +0000765private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 /// For diagnostics, and checking the assembler temporary
767 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000768
Eric Christopher8996c5d2013-03-15 00:42:55 +0000769 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000770 const char *Data;
771 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000772 };
773
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 struct RegIdxOp {
775 unsigned Index; /// Index into the register class
776 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000777 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000779 };
780
781 struct ImmOp {
782 const MCExpr *Val;
783 };
784
785 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000787 const MCExpr *Off;
788 };
789
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000790 struct RegListOp {
791 SmallVector<unsigned, 10> *List;
792 };
793
Jack Carterb4dbc172012-09-05 23:34:03 +0000794 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000795 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000797 struct ImmOp Imm;
798 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000799 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000800 };
801
802 SMLoc StartLoc, EndLoc;
803
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000805 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
806 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000807 const MCRegisterInfo *RegInfo,
808 SMLoc S, SMLoc E,
809 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000810 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 Op->RegIdx.Index = Index;
812 Op->RegIdx.RegInfo = RegInfo;
813 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000814 Op->RegIdx.Tok.Data = Str.data();
815 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 Op->StartLoc = S;
817 Op->EndLoc = E;
818 return Op;
819 }
820
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000821public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000822 /// Coerce the register to GPR32 and return the real register for the current
823 /// target.
824 unsigned getGPR32Reg() const {
825 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000826 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 unsigned ClassID = Mips::GPR32RegClassID;
828 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000829 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000830
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000831 /// Coerce the register to GPR32 and return the real register for the current
832 /// target.
833 unsigned getGPRMM16Reg() const {
834 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
835 unsigned ClassID = Mips::GPR32RegClassID;
836 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
837 }
838
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 /// Coerce the register to GPR64 and return the real register for the current
840 /// target.
841 unsigned getGPR64Reg() const {
842 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
843 unsigned ClassID = Mips::GPR64RegClassID;
844 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000845 }
846
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847private:
848 /// Coerce the register to AFGR64 and return the real register for the current
849 /// target.
850 unsigned getAFGR64Reg() const {
851 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
852 if (RegIdx.Index % 2 != 0)
853 AsmParser.Warning(StartLoc, "Float register should be even.");
854 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
855 .getRegister(RegIdx.Index / 2);
856 }
857
858 /// Coerce the register to FGR64 and return the real register for the current
859 /// target.
860 unsigned getFGR64Reg() const {
861 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
862 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
863 .getRegister(RegIdx.Index);
864 }
865
866 /// Coerce the register to FGR32 and return the real register for the current
867 /// target.
868 unsigned getFGR32Reg() const {
869 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
870 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
871 .getRegister(RegIdx.Index);
872 }
873
874 /// Coerce the register to FGRH32 and return the real register for the current
875 /// target.
876 unsigned getFGRH32Reg() const {
877 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
878 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
879 .getRegister(RegIdx.Index);
880 }
881
882 /// Coerce the register to FCC and return the real register for the current
883 /// target.
884 unsigned getFCCReg() const {
885 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
886 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
887 .getRegister(RegIdx.Index);
888 }
889
890 /// Coerce the register to MSA128 and return the real register for the current
891 /// target.
892 unsigned getMSA128Reg() const {
893 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
894 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
895 // identical
896 unsigned ClassID = Mips::MSA128BRegClassID;
897 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
898 }
899
900 /// Coerce the register to MSACtrl and return the real register for the
901 /// current target.
902 unsigned getMSACtrlReg() const {
903 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
904 unsigned ClassID = Mips::MSACtrlRegClassID;
905 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
906 }
907
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000908 /// Coerce the register to COP0 and return the real register for the
909 /// current target.
910 unsigned getCOP0Reg() const {
911 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
912 unsigned ClassID = Mips::COP0RegClassID;
913 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
914 }
915
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000916 /// Coerce the register to COP2 and return the real register for the
917 /// current target.
918 unsigned getCOP2Reg() const {
919 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
920 unsigned ClassID = Mips::COP2RegClassID;
921 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
922 }
923
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000924 /// Coerce the register to COP3 and return the real register for the
925 /// current target.
926 unsigned getCOP3Reg() const {
927 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
928 unsigned ClassID = Mips::COP3RegClassID;
929 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
930 }
931
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 /// Coerce the register to ACC64DSP and return the real register for the
933 /// current target.
934 unsigned getACC64DSPReg() const {
935 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
936 unsigned ClassID = Mips::ACC64DSPRegClassID;
937 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
938 }
939
940 /// Coerce the register to HI32DSP and return the real register for the
941 /// current target.
942 unsigned getHI32DSPReg() const {
943 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
944 unsigned ClassID = Mips::HI32DSPRegClassID;
945 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
946 }
947
948 /// Coerce the register to LO32DSP and return the real register for the
949 /// current target.
950 unsigned getLO32DSPReg() const {
951 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
952 unsigned ClassID = Mips::LO32DSPRegClassID;
953 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
954 }
955
956 /// Coerce the register to CCR and return the real register for the
957 /// current target.
958 unsigned getCCRReg() const {
959 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
960 unsigned ClassID = Mips::CCRRegClassID;
961 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
962 }
963
964 /// Coerce the register to HWRegs and return the real register for the
965 /// current target.
966 unsigned getHWRegsReg() const {
967 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
968 unsigned ClassID = Mips::HWRegsRegClassID;
969 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
970 }
971
972public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000973 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000974 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000975 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000976 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000977 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000978 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000979 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000980 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000981 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000982
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000983 void addRegOperands(MCInst &Inst, unsigned N) const {
984 llvm_unreachable("Use a custom parser instead");
985 }
986
Daniel Sanders21bce302014-04-01 12:35:23 +0000987 /// Render the operand to an MCInst as a GPR32
988 /// Asserts if the wrong number of operands are requested, or the operand
989 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000990 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
991 assert(N == 1 && "Invalid number of operands!");
992 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
993 }
994
995 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 1 && "Invalid number of operands!");
997 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
998 }
999
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1001 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001002 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001003 }
1004
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001005 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1006 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001007 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001008 }
1009
Jozef Kolek1904fa22014-11-24 14:25:53 +00001010 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1011 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001012 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001013 }
1014
Zoran Jovanovic41688672015-02-10 16:36:20 +00001015 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1016 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001017 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001018 }
1019
Daniel Sanders21bce302014-04-01 12:35:23 +00001020 /// Render the operand to an MCInst as a GPR64
1021 /// Asserts if the wrong number of operands are requested, or the operand
1022 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001023 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1024 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001025 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 }
1027
1028 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1029 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001030 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 }
1032
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001033 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1034 assert(N == 1 && "Invalid number of operands!");
1035 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1036 }
1037
1038 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1039 assert(N == 1 && "Invalid number of operands!");
1040 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1041 }
1042
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1044 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001045 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 }
1047
1048 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1049 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001050 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001051 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001052 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001053 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001054 AsmParser.getParser().printError(
1055 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1056 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 }
1058
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001059 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1060 assert(N == 1 && "Invalid number of operands!");
1061 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1062 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1063 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1064 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1065 "registers");
1066 }
1067
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001070 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 }
1072
1073 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001075 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001076 }
1077
1078 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001080 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001081 }
1082
1083 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1084 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001085 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001086 }
1087
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001088 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1089 assert(N == 1 && "Invalid number of operands!");
1090 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1091 }
1092
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001093 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001095 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 }
1097
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001098 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1099 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001100 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001101 }
1102
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001103 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1104 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001105 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001106 }
1107
1108 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001110 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001111 }
1112
1113 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1114 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001115 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 }
1117
1118 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001120 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001121 }
1122
1123 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1124 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001125 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 }
1127
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001128 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001129 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001131 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001132 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001133 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001134 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001135 Inst.addOperand(MCOperand::createImm(Imm));
1136 }
1137
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001138 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001139 void addSImmOperands(MCInst &Inst, unsigned N) const {
1140 if (isImm() && !isConstantImm()) {
1141 addExpr(Inst, getImm());
1142 return;
1143 }
1144 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1145 }
1146
1147 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001148 void addUImmOperands(MCInst &Inst, unsigned N) const {
1149 if (isImm() && !isConstantImm()) {
1150 addExpr(Inst, getImm());
1151 return;
1152 }
1153 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1154 }
1155
Daniel Sanders78e89022016-03-11 11:37:50 +00001156 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1157 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1158 assert(N == 1 && "Invalid number of operands!");
1159 int64_t Imm = getConstantImm() - Offset;
1160 Imm = SignExtend64<Bits>(Imm);
1161 Imm += Offset;
1162 Imm += AdjustOffset;
1163 Inst.addOperand(MCOperand::createImm(Imm));
1164 }
1165
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001166 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001167 assert(N == 1 && "Invalid number of operands!");
1168 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001170 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001171
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001172 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001173 assert(N == 2 && "Invalid number of operands!");
1174
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001175 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1176 ? getMemBase()->getGPR64Reg()
1177 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001178
1179 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001180 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001181 }
1182
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001183 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1184 assert(N == 2 && "Invalid number of operands!");
1185
Jim Grosbache9119e42015-05-13 18:37:00 +00001186 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001187
1188 const MCExpr *Expr = getMemOff();
1189 addExpr(Inst, Expr);
1190 }
1191
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001192 void addRegListOperands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194
1195 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001196 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001197 }
1198
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001199 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1200 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001201 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001202 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001203 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1204 Inst.addOperand(MCOperand::createReg(
1205 RegIdx.RegInfo->getRegClass(
1206 AsmParser.getABI().AreGprs64bit()
1207 ? Mips::GPR64RegClassID
1208 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1209 Inst.addOperand(MCOperand::createReg(
1210 RegIdx.RegInfo->getRegClass(
1211 AsmParser.getABI().AreGprs64bit()
1212 ? Mips::GPR64RegClassID
1213 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001214 }
1215
Zoran Jovanovic41688672015-02-10 16:36:20 +00001216 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 2 && "Invalid number of operands!");
1218 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001219 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001220 }
1221
Craig Topper56c590a2014-04-29 07:58:02 +00001222 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001223 // As a special case until we sort out the definition of div/divu, accept
1224 // $0/$zero here so that MCK_ZERO works correctly.
1225 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001226 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001227
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001228 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001229 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001230
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001231 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001232 int64_t Res;
1233 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001235
Daniel Sanders52da7af2015-11-06 12:11:03 +00001236 bool isConstantImmz() const {
1237 return isConstantImm() && getConstantImm() == 0;
1238 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001239
Daniel Sandersea4f6532015-11-06 12:22:31 +00001240 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1241 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1242 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001243
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001244 template <unsigned Bits> bool isSImm() const {
1245 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1246 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001247
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001248 template <unsigned Bits> bool isUImm() const {
1249 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1250 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001251
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001252 template <unsigned Bits> bool isAnyImm() const {
1253 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1254 isUInt<Bits>(getConstantImm()))
1255 : isImm();
1256 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001257
Daniel Sanders78e89022016-03-11 11:37:50 +00001258 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1259 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001260 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001261
Hrvoje Varga46458d02016-02-25 12:53:29 +00001262 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1263 return isConstantImm() && getConstantImm() >= Bottom &&
1264 getConstantImm() <= Top;
1265 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Craig Topper56c590a2014-04-29 07:58:02 +00001267 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001268 // Note: It's not possible to pretend that other operand kinds are tokens.
1269 // The matcher emitter checks tokens first.
1270 return Kind == k_Token;
1271 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001272
Craig Topper56c590a2014-04-29 07:58:02 +00001273 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001274
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001275 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001276 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001277 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001278
Simon Dardis4ccda502016-05-27 13:56:36 +00001279 // Allow relocation operators.
1280 // FIXME: This predicate and others need to look through binary expressions
1281 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001282 template <unsigned Bits, unsigned ShiftAmount = 0>
1283 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001284 if (!isMem())
1285 return false;
1286 if (!getMemBase()->isGPRAsmReg())
1287 return false;
1288 if (isa<MCTargetExpr>(getMemOff()) ||
1289 (isConstantMemOff() &&
1290 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1291 return true;
1292 MCValue Res;
1293 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1294 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001295 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001296
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001297 bool isMemWithGRPMM16Base() const {
1298 return isMem() && getMemBase()->isMM16AsmReg();
1299 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001300
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001301 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1302 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1303 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Jozef Kolek12c69822014-12-23 16:16:33 +00001306 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1307 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1308 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1309 && (getMemBase()->getGPR32Reg() == Mips::SP);
1310 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001311
Daniel Sanderse473dc92016-05-09 13:38:25 +00001312 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1313 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1314 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1315 && (getMemBase()->getGPR32Reg() == Mips::GP);
1316 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001317
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001318 template <unsigned Bits, unsigned ShiftLeftAmount>
1319 bool isScaledUImm() const {
1320 return isConstantImm() &&
1321 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001322 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001323
Daniel Sanders97297772016-03-22 14:40:00 +00001324 template <unsigned Bits, unsigned ShiftLeftAmount>
1325 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001326 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1327 return true;
1328 // Operand can also be a symbol or symbol plus offset in case of relocations.
1329 if (Kind != k_Immediate)
1330 return false;
1331 MCValue Res;
1332 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1333 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001334 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001335
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001336 bool isRegList16() const {
1337 if (!isRegList())
1338 return false;
1339
1340 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001341 if (Size < 2 || Size > 5)
1342 return false;
1343
1344 unsigned R0 = RegList.List->front();
1345 unsigned R1 = RegList.List->back();
1346 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1347 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001348 return false;
1349
1350 int PrevReg = *RegList.List->begin();
1351 for (int i = 1; i < Size - 1; i++) {
1352 int Reg = (*(RegList.List))[i];
1353 if ( Reg != PrevReg + 1)
1354 return false;
1355 PrevReg = Reg;
1356 }
1357
1358 return true;
1359 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001360
Vladimir Medic2b953d02013-10-01 09:48:56 +00001361 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001362
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001363 bool isLSAImm() const {
1364 if (!isConstantImm())
1365 return false;
1366 int64_t Val = getConstantImm();
1367 return 1 <= Val && Val <= 4;
1368 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001369
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001370 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001371
Zoran Jovanovic41688672015-02-10 16:36:20 +00001372 bool isMovePRegPair() const {
1373 if (Kind != k_RegList || RegList.List->size() != 2)
1374 return false;
1375
1376 unsigned R0 = RegList.List->front();
1377 unsigned R1 = RegList.List->back();
1378
1379 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1380 (R0 == Mips::A1 && R1 == Mips::A3) ||
1381 (R0 == Mips::A2 && R1 == Mips::A3) ||
1382 (R0 == Mips::A0 && R1 == Mips::S5) ||
1383 (R0 == Mips::A0 && R1 == Mips::S6) ||
1384 (R0 == Mips::A0 && R1 == Mips::A1) ||
1385 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001386 (R0 == Mips::A0 && R1 == Mips::A3) ||
1387 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1388 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1389 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1390 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1391 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1392 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1393 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1394 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001395 return true;
1396
1397 return false;
1398 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001399
1400 StringRef getToken() const {
1401 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001402 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001403 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001404
Zlatko Buljanba553a62016-05-09 08:07:28 +00001405 bool isRegPair() const {
1406 return Kind == k_RegPair && RegIdx.Index <= 30;
1407 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001408
Craig Topper56c590a2014-04-29 07:58:02 +00001409 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001410 // As a special case until we sort out the definition of div/divu, accept
1411 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001412 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1413 RegIdx.Kind & RegKind_GPR)
1414 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001415
Daniel Sanders976d9382016-07-05 13:38:40 +00001416 llvm_unreachable("Invalid access!");
1417 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001418 }
1419
Jack Carterb4dbc172012-09-05 23:34:03 +00001420 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001421 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001422 return Imm.Val;
1423 }
1424
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001425 int64_t getConstantImm() const {
1426 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001427 int64_t Value = 0;
1428 (void)Val->evaluateAsAbsolute(Value);
1429 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001430 }
1431
1432 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001433 assert((Kind == k_Memory) && "Invalid access!");
1434 return Mem.Base;
1435 }
1436
1437 const MCExpr *getMemOff() const {
1438 assert((Kind == k_Memory) && "Invalid access!");
1439 return Mem.Off;
1440 }
1441
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001442 int64_t getConstantMemOff() const {
1443 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1444 }
1445
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001446 const SmallVectorImpl<unsigned> &getRegList() const {
1447 assert((Kind == k_RegList) && "Invalid access!");
1448 return *(RegList.List);
1449 }
1450
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001451 unsigned getRegPair() const {
1452 assert((Kind == k_RegPair) && "Invalid access!");
1453 return RegIdx.Index;
1454 }
1455
David Blaikie960ea3f2014-06-08 16:18:35 +00001456 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1457 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001458 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001459 Op->Tok.Data = Str.data();
1460 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001461 Op->StartLoc = S;
1462 Op->EndLoc = S;
1463 return Op;
1464 }
1465
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001466 /// Create a numeric register (e.g. $1). The exact register remains
1467 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001468 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001469 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1470 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001471 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001472 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001473 }
1474
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001475 /// Create a register that is definitely a GPR.
1476 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001477 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001478 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1479 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1480 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001481 }
1482
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001483 /// Create a register that is definitely a FGR.
1484 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001485 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001486 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1487 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1488 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001489 }
1490
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001491 /// Create a register that is definitely a HWReg.
1492 /// This is typically only used for named registers such as $hwr_cpunum.
1493 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001494 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001495 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001496 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001497 }
1498
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001499 /// Create a register that is definitely an FCC.
1500 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001501 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001502 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1503 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1504 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001505 }
1506
1507 /// Create a register that is definitely an ACC.
1508 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001509 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001510 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1511 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1512 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001513 }
1514
1515 /// Create a register that is definitely an MSA128.
1516 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001517 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001518 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1519 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1520 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001521 }
1522
1523 /// Create a register that is definitely an MSACtrl.
1524 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001525 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001526 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1527 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1528 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001529 }
1530
David Blaikie960ea3f2014-06-08 16:18:35 +00001531 static std::unique_ptr<MipsOperand>
1532 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001533 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001534 Op->Imm.Val = Val;
1535 Op->StartLoc = S;
1536 Op->EndLoc = E;
1537 return Op;
1538 }
1539
David Blaikie960ea3f2014-06-08 16:18:35 +00001540 static std::unique_ptr<MipsOperand>
1541 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1542 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001543 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001544 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001545 Op->Mem.Off = Off;
1546 Op->StartLoc = S;
1547 Op->EndLoc = E;
1548 return Op;
1549 }
1550
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001551 static std::unique_ptr<MipsOperand>
1552 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1553 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001554 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001555
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001556 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001557 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001558 Op->StartLoc = StartLoc;
1559 Op->EndLoc = EndLoc;
1560 return Op;
1561 }
1562
Daniel Sandersd044e492016-05-09 13:10:57 +00001563 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1564 SMLoc S, SMLoc E,
1565 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001566 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001567 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001568 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1569 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001570 Op->StartLoc = S;
1571 Op->EndLoc = E;
1572 return Op;
1573 }
1574
Simon Dardis509da1a2017-02-13 16:06:48 +00001575 bool isGPRZeroAsmReg() const {
1576 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1577 }
1578
1579 bool isGPRNonZeroAsmReg() const {
1580 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1581 RegIdx.Index <= 31;
1582 }
1583
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001584 bool isGPRAsmReg() const {
1585 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001587
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001588 bool isMM16AsmReg() const {
1589 if (!(isRegIdx() && RegIdx.Kind))
1590 return false;
1591 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1592 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001593
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001594 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001595 bool isMM16AsmRegZero() const {
1596 if (!(isRegIdx() && RegIdx.Kind))
1597 return false;
1598 return (RegIdx.Index == 0 ||
1599 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1600 RegIdx.Index == 17);
1601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001602
Zoran Jovanovic41688672015-02-10 16:36:20 +00001603 bool isMM16AsmRegMoveP() const {
1604 if (!(isRegIdx() && RegIdx.Kind))
1605 return false;
1606 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1607 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1608 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001609
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001610 bool isFGRAsmReg() const {
1611 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1612 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001613 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001614
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001615 bool isStrictlyFGRAsmReg() const {
1616 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1617 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1618 }
1619
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001620 bool isHWRegsAsmReg() const {
1621 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001622 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001623
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001624 bool isCCRAsmReg() const {
1625 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001626 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001627
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001628 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001629 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1630 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001631 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001632 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001633
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001634 bool isACCAsmReg() const {
1635 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001636 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001637
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001638 bool isCOP0AsmReg() const {
1639 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1640 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001641
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001642 bool isCOP2AsmReg() const {
1643 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001644 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001645
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001646 bool isCOP3AsmReg() const {
1647 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1648 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001649
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001650 bool isMSA128AsmReg() const {
1651 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001652 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001653
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001654 bool isMSACtrlAsmReg() const {
1655 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001656 }
1657
Jack Carterb4dbc172012-09-05 23:34:03 +00001658 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001659 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001660 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001661 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001662
Craig Topper56c590a2014-04-29 07:58:02 +00001663 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001664 switch (Kind) {
1665 case k_Immediate:
1666 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001667 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001668 OS << ">";
1669 break;
1670 case k_Memory:
1671 OS << "Mem<";
1672 Mem.Base->print(OS);
1673 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001674 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001675 OS << ">";
1676 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001677 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001678 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1679 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001680 break;
1681 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001682 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001683 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001684 case k_RegList:
1685 OS << "RegList< ";
1686 for (auto Reg : (*RegList.List))
1687 OS << Reg << " ";
1688 OS << ">";
1689 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001690 case k_RegPair:
1691 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1692 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001693 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001694 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001695
1696 bool isValidForTie(const MipsOperand &Other) const {
1697 if (Kind != Other.Kind)
1698 return false;
1699
1700 switch (Kind) {
1701 default:
1702 llvm_unreachable("Unexpected kind");
1703 return false;
1704 case k_RegisterIndex: {
1705 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1706 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1707 return Token == OtherToken;
1708 }
1709 }
1710 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001711}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001712
1713} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001714
Jack Carter9e65aa32013-03-22 00:05:30 +00001715namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001716
Jack Carter9e65aa32013-03-22 00:05:30 +00001717extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001718
1719} // end namespace llvm
1720
Jack Carter9e65aa32013-03-22 00:05:30 +00001721static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1722 return MipsInsts[Opcode];
1723}
1724
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001725static bool hasShortDelaySlot(unsigned Opcode) {
1726 switch (Opcode) {
1727 case Mips::JALS_MM:
1728 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001729 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001730 case Mips::BGEZALS_MM:
1731 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001732 return true;
1733 default:
1734 return false;
1735 }
1736}
1737
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001738static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1739 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1740 return &SRExpr->getSymbol();
1741 }
1742
1743 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1744 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1745 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1746
1747 if (LHSSym)
1748 return LHSSym;
1749
1750 if (RHSSym)
1751 return RHSSym;
1752
1753 return nullptr;
1754 }
1755
1756 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1757 return getSingleMCSymbol(UExpr->getSubExpr());
1758
1759 return nullptr;
1760}
1761
1762static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1763 if (isa<MCSymbolRefExpr>(Expr))
1764 return 1;
1765
1766 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1767 return countMCSymbolRefExpr(BExpr->getLHS()) +
1768 countMCSymbolRefExpr(BExpr->getRHS());
1769
1770 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1771 return countMCSymbolRefExpr(UExpr->getSubExpr());
1772
1773 return 0;
1774}
1775
Jack Carter9e65aa32013-03-22 00:05:30 +00001776bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001777 MCStreamer &Out,
1778 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001779 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001780 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001781 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001782
Jack Carter9e65aa32013-03-22 00:05:30 +00001783 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001784
1785 if (MCID.isBranch() || MCID.isCall()) {
1786 const unsigned Opcode = Inst.getOpcode();
1787 MCOperand Offset;
1788
1789 switch (Opcode) {
1790 default:
1791 break;
Kai Nackee0245392015-01-27 19:11:28 +00001792 case Mips::BBIT0:
1793 case Mips::BBIT032:
1794 case Mips::BBIT1:
1795 case Mips::BBIT132:
1796 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001797 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001798
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001799 case Mips::BEQ:
1800 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001801 case Mips::BEQ_MM:
1802 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001803 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001804 Offset = Inst.getOperand(2);
1805 if (!Offset.isImm())
1806 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001807 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001808 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001809 if (OffsetToAlignment(Offset.getImm(),
1810 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001811 return Error(IDLoc, "branch to misaligned address");
1812 break;
1813 case Mips::BGEZ:
1814 case Mips::BGTZ:
1815 case Mips::BLEZ:
1816 case Mips::BLTZ:
1817 case Mips::BGEZAL:
1818 case Mips::BLTZAL:
1819 case Mips::BC1F:
1820 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001821 case Mips::BGEZ_MM:
1822 case Mips::BGTZ_MM:
1823 case Mips::BLEZ_MM:
1824 case Mips::BLTZ_MM:
1825 case Mips::BGEZAL_MM:
1826 case Mips::BLTZAL_MM:
1827 case Mips::BC1F_MM:
1828 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001829 case Mips::BC1EQZC_MMR6:
1830 case Mips::BC1NEZC_MMR6:
1831 case Mips::BC2EQZC_MMR6:
1832 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001833 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001834 Offset = Inst.getOperand(1);
1835 if (!Offset.isImm())
1836 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001837 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001838 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001839 if (OffsetToAlignment(Offset.getImm(),
1840 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001841 return Error(IDLoc, "branch to misaligned address");
1842 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001843 case Mips::BGEC: case Mips::BGEC_MMR6:
1844 case Mips::BLTC: case Mips::BLTC_MMR6:
1845 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1846 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1847 case Mips::BEQC: case Mips::BEQC_MMR6:
1848 case Mips::BNEC: case Mips::BNEC_MMR6:
1849 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1850 Offset = Inst.getOperand(2);
1851 if (!Offset.isImm())
1852 break; // We'll deal with this situation later on when applying fixups.
1853 if (!isIntN(18, Offset.getImm()))
1854 return Error(IDLoc, "branch target out of range");
1855 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1856 return Error(IDLoc, "branch to misaligned address");
1857 break;
1858 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1859 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1860 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1861 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1862 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1863 Offset = Inst.getOperand(1);
1864 if (!Offset.isImm())
1865 break; // We'll deal with this situation later on when applying fixups.
1866 if (!isIntN(18, Offset.getImm()))
1867 return Error(IDLoc, "branch target out of range");
1868 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1869 return Error(IDLoc, "branch to misaligned address");
1870 break;
1871 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1872 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1873 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1874 Offset = Inst.getOperand(1);
1875 if (!Offset.isImm())
1876 break; // We'll deal with this situation later on when applying fixups.
1877 if (!isIntN(23, Offset.getImm()))
1878 return Error(IDLoc, "branch target out of range");
1879 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1880 return Error(IDLoc, "branch to misaligned address");
1881 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001882 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001883 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001884 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001885 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001886 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1887 Offset = Inst.getOperand(1);
1888 if (!Offset.isImm())
1889 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001890 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001891 return Error(IDLoc, "branch target out of range");
1892 if (OffsetToAlignment(Offset.getImm(), 2LL))
1893 return Error(IDLoc, "branch to misaligned address");
1894 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001895 }
1896 }
1897
Daniel Sandersa84989a2014-06-16 13:25:35 +00001898 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1899 // We still accept it but it is a normal nop.
1900 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1901 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1902 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1903 "nop instruction");
1904 }
1905
Kai Nackee0245392015-01-27 19:11:28 +00001906 if (hasCnMips()) {
1907 const unsigned Opcode = Inst.getOpcode();
1908 MCOperand Opnd;
1909 int Imm;
1910
1911 switch (Opcode) {
1912 default:
1913 break;
1914
1915 case Mips::BBIT0:
1916 case Mips::BBIT032:
1917 case Mips::BBIT1:
1918 case Mips::BBIT132:
1919 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1920 // The offset is handled above
1921 Opnd = Inst.getOperand(1);
1922 if (!Opnd.isImm())
1923 return Error(IDLoc, "expected immediate operand kind");
1924 Imm = Opnd.getImm();
1925 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1926 Opcode == Mips::BBIT1 ? 63 : 31))
1927 return Error(IDLoc, "immediate operand value out of range");
1928 if (Imm > 31) {
1929 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1930 : Mips::BBIT132);
1931 Inst.getOperand(1).setImm(Imm - 32);
1932 }
1933 break;
1934
Kai Nackee0245392015-01-27 19:11:28 +00001935 case Mips::SEQi:
1936 case Mips::SNEi:
1937 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1938 Opnd = Inst.getOperand(2);
1939 if (!Opnd.isImm())
1940 return Error(IDLoc, "expected immediate operand kind");
1941 Imm = Opnd.getImm();
1942 if (!isInt<10>(Imm))
1943 return Error(IDLoc, "immediate operand value out of range");
1944 break;
1945 }
1946 }
1947
Simon Dardis509da1a2017-02-13 16:06:48 +00001948 // Warn on division by zero. We're checking here as all instructions get
1949 // processed here, not just the macros that need expansion.
1950 //
1951 // The MIPS backend models most of the divison instructions and macros as
1952 // three operand instructions. The pre-R6 divide instructions however have
1953 // two operands and explicitly define HI/LO as part of the instruction,
1954 // not in the operands.
1955 unsigned FirstOp = 1;
1956 unsigned SecondOp = 2;
1957 switch (Inst.getOpcode()) {
1958 default:
1959 break;
1960 case Mips::SDivIMacro:
1961 case Mips::UDivIMacro:
1962 case Mips::DSDivIMacro:
1963 case Mips::DUDivIMacro:
1964 if (Inst.getOperand(2).getImm() == 0) {
1965 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1966 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1967 Warning(IDLoc, "dividing zero by zero");
1968 else
1969 Warning(IDLoc, "division by zero");
1970 }
1971 break;
1972 case Mips::DSDIV:
1973 case Mips::SDIV:
1974 case Mips::UDIV:
1975 case Mips::DUDIV:
1976 case Mips::UDIV_MM:
1977 case Mips::SDIV_MM:
1978 FirstOp = 0;
1979 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001980 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001981 case Mips::SDivMacro:
1982 case Mips::DSDivMacro:
1983 case Mips::UDivMacro:
1984 case Mips::DUDivMacro:
1985 case Mips::DIV:
1986 case Mips::DIVU:
1987 case Mips::DDIV:
1988 case Mips::DDIVU:
1989 case Mips::DIVU_MMR6:
1990 case Mips::DDIVU_MM64R6:
1991 case Mips::DIV_MMR6:
1992 case Mips::DDIV_MM64R6:
1993 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1994 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1995 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1996 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1997 Warning(IDLoc, "dividing zero by zero");
1998 else
1999 Warning(IDLoc, "division by zero");
2000 }
2001 break;
2002 }
2003
Simon Atanasyan50485142016-12-12 17:40:26 +00002004 // For PIC code convert unconditional jump to unconditional branch.
2005 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2006 inPicMode()) {
2007 MCInst BInst;
2008 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2009 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2010 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2011 BInst.addOperand(Inst.getOperand(0));
2012 Inst = BInst;
2013 }
2014
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002015 // This expansion is not in a function called by tryExpandInstruction()
2016 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002017 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2018 inPicMode()) {
2019 warnIfNoMacro(IDLoc);
2020
2021 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2022
2023 // We can do this expansion if there's only 1 symbol in the argument
2024 // expression.
2025 if (countMCSymbolRefExpr(JalExpr) > 1)
2026 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2027
2028 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002029 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002030 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2031
2032 // FIXME: Add support for label+offset operands (currently causes an error).
2033 // FIXME: Add support for forward-declared local symbols.
2034 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002035 if (JalSym->isInSection() || JalSym->isTemporary() ||
2036 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002037 if (isABI_O32()) {
2038 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002039 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002040 // R_(MICRO)MIPS_GOT16 label
2041 // addiu $25, $25, 0
2042 // R_(MICRO)MIPS_LO16 label
2043 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002044 const MCExpr *Got16RelocExpr =
2045 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2046 const MCExpr *Lo16RelocExpr =
2047 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002048
Daniel Sandersa736b372016-04-29 13:33:12 +00002049 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2050 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2051 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2052 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002053 } else if (isABI_N32() || isABI_N64()) {
2054 // If it's a local symbol and the N32/N64 ABIs are being used,
2055 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002056 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002057 // R_(MICRO)MIPS_GOT_DISP label
2058 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002059 const MCExpr *GotDispRelocExpr =
2060 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002061
Daniel Sandersa736b372016-04-29 13:33:12 +00002062 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2063 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2064 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002065 }
2066 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002067 // If it's an external/weak symbol, we expand to:
2068 // lw/ld $25, 0($gp)
2069 // R_(MICRO)MIPS_CALL16 label
2070 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002071 const MCExpr *Call16RelocExpr =
2072 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002073
Daniel Sandersa736b372016-04-29 13:33:12 +00002074 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2075 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002076 }
2077
2078 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002079 if (IsCpRestoreSet && inMicroMipsMode())
2080 JalrInst.setOpcode(Mips::JALRS_MM);
2081 else
2082 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002083 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2084 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2085
2086 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2087 // This relocation is supposed to be an optimization hint for the linker
2088 // and is not necessary for correctness.
2089
2090 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002091 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002092 }
2093
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002094 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2095 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 // reference or immediate we may have to expand instructions.
2098 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002099 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002100 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2101 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 MCOperand &Op = Inst.getOperand(i);
2103 if (Op.isImm()) {
2104 int MemOffset = Op.getImm();
2105 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002106 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002107 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002108 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002109 }
2110 } else if (Op.isExpr()) {
2111 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002112 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002113 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002114 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002115 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002117 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002118 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002119 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002120 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002121 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002122 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002123 }
2124 }
2125 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002126 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002127 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002128
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002129 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002130 if (MCID.mayLoad()) {
2131 // Try to create 16-bit GP relative load instruction.
2132 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2133 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2134 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2135 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2136 MCOperand &Op = Inst.getOperand(i);
2137 if (Op.isImm()) {
2138 int MemOffset = Op.getImm();
2139 MCOperand &DstReg = Inst.getOperand(0);
2140 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002141 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002142 getContext().getRegisterInfo()->getRegClass(
2143 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002144 (BaseReg.getReg() == Mips::GP ||
2145 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002146
Daniel Sandersa736b372016-04-29 13:33:12 +00002147 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2148 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002149 return false;
2150 }
2151 }
2152 }
2153 } // for
2154 } // if load
2155
2156 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2157
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002158 MCOperand Opnd;
2159 int Imm;
2160
2161 switch (Inst.getOpcode()) {
2162 default:
2163 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002164 case Mips::ADDIUSP_MM:
2165 Opnd = Inst.getOperand(0);
2166 if (!Opnd.isImm())
2167 return Error(IDLoc, "expected immediate operand kind");
2168 Imm = Opnd.getImm();
2169 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2170 Imm % 4 != 0)
2171 return Error(IDLoc, "immediate operand value out of range");
2172 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002173 case Mips::SLL16_MM:
2174 case Mips::SRL16_MM:
2175 Opnd = Inst.getOperand(2);
2176 if (!Opnd.isImm())
2177 return Error(IDLoc, "expected immediate operand kind");
2178 Imm = Opnd.getImm();
2179 if (Imm < 1 || Imm > 8)
2180 return Error(IDLoc, "immediate operand value out of range");
2181 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002182 case Mips::LI16_MM:
2183 Opnd = Inst.getOperand(1);
2184 if (!Opnd.isImm())
2185 return Error(IDLoc, "expected immediate operand kind");
2186 Imm = Opnd.getImm();
2187 if (Imm < -1 || Imm > 126)
2188 return Error(IDLoc, "immediate operand value out of range");
2189 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002190 case Mips::ADDIUR2_MM:
2191 Opnd = Inst.getOperand(2);
2192 if (!Opnd.isImm())
2193 return Error(IDLoc, "expected immediate operand kind");
2194 Imm = Opnd.getImm();
2195 if (!(Imm == 1 || Imm == -1 ||
2196 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2197 return Error(IDLoc, "immediate operand value out of range");
2198 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002199 case Mips::ANDI16_MM:
2200 Opnd = Inst.getOperand(2);
2201 if (!Opnd.isImm())
2202 return Error(IDLoc, "expected immediate operand kind");
2203 Imm = Opnd.getImm();
2204 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2205 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2206 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2207 return Error(IDLoc, "immediate operand value out of range");
2208 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002209 case Mips::LBU16_MM:
2210 Opnd = Inst.getOperand(2);
2211 if (!Opnd.isImm())
2212 return Error(IDLoc, "expected immediate operand kind");
2213 Imm = Opnd.getImm();
2214 if (Imm < -1 || Imm > 14)
2215 return Error(IDLoc, "immediate operand value out of range");
2216 break;
2217 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002218 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002219 Opnd = Inst.getOperand(2);
2220 if (!Opnd.isImm())
2221 return Error(IDLoc, "expected immediate operand kind");
2222 Imm = Opnd.getImm();
2223 if (Imm < 0 || Imm > 15)
2224 return Error(IDLoc, "immediate operand value out of range");
2225 break;
2226 case Mips::LHU16_MM:
2227 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002228 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002229 Opnd = Inst.getOperand(2);
2230 if (!Opnd.isImm())
2231 return Error(IDLoc, "expected immediate operand kind");
2232 Imm = Opnd.getImm();
2233 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2234 return Error(IDLoc, "immediate operand value out of range");
2235 break;
2236 case Mips::LW16_MM:
2237 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002238 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002239 Opnd = Inst.getOperand(2);
2240 if (!Opnd.isImm())
2241 return Error(IDLoc, "expected immediate operand kind");
2242 Imm = Opnd.getImm();
2243 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2244 return Error(IDLoc, "immediate operand value out of range");
2245 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002246 case Mips::ADDIUPC_MM:
2247 MCOperand Opnd = Inst.getOperand(1);
2248 if (!Opnd.isImm())
2249 return Error(IDLoc, "expected immediate operand kind");
2250 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002251 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002252 return Error(IDLoc, "immediate operand value out of range");
2253 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002254 }
2255 }
2256
Daniel Sandersd8c07762016-04-18 12:35:36 +00002257 bool FillDelaySlot =
2258 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2259 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002260 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002261
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002262 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002263 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002264 switch (ExpandResult) {
2265 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002266 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002267 break;
2268 case MER_Success:
2269 break;
2270 case MER_Fail:
2271 return true;
2272 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002273
Daniel Sanderscda908a2016-05-16 09:10:13 +00002274 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2275 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002276 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002277 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002278 TOut.updateABIInfo(*this);
2279 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002280
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002281 // If this instruction has a delay slot and .set reorder is active,
2282 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002283 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002284 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2285 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002286 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002287
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002288 if ((Inst.getOpcode() == Mips::JalOneReg ||
2289 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2290 isPicAndNotNxxAbi()) {
2291 if (IsCpRestoreSet) {
2292 // We need a NOP between the JALR and the LW:
2293 // If .set reorder has been used, we've already emitted a NOP.
2294 // If .set noreorder has been used, we need to emit a NOP at this point.
2295 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002296 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2297 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002298
2299 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002300 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002301 } else
2302 Warning(IDLoc, "no .cprestore used in PIC mode");
2303 }
2304
Jack Carter9e65aa32013-03-22 00:05:30 +00002305 return false;
2306}
2307
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002308MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002309MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2310 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002311 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002312 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002313 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002314 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002315 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002316 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002317 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002318 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002319 case Mips::LoadAddrImm64:
2320 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2321 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2322 "expected immediate operand kind");
2323
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002324 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2325 Inst.getOperand(1),
2326 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002327 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002328 ? MER_Fail
2329 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002330 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002331 case Mips::LoadAddrReg64:
2332 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2333 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2334 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2335 "expected immediate operand kind");
2336
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002337 return expandLoadAddress(Inst.getOperand(0).getReg(),
2338 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2339 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002340 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002341 ? MER_Fail
2342 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002343 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002344 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002345 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2346 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002347 case Mips::SWM_MM:
2348 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002349 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2350 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002351 case Mips::JalOneReg:
2352 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002353 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002354 case Mips::BneImm:
2355 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002356 case Mips::BEQLImmMacro:
2357 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002358 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002359 case Mips::BLT:
2360 case Mips::BLE:
2361 case Mips::BGE:
2362 case Mips::BGT:
2363 case Mips::BLTU:
2364 case Mips::BLEU:
2365 case Mips::BGEU:
2366 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002367 case Mips::BLTL:
2368 case Mips::BLEL:
2369 case Mips::BGEL:
2370 case Mips::BGTL:
2371 case Mips::BLTUL:
2372 case Mips::BLEUL:
2373 case Mips::BGEUL:
2374 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002375 case Mips::BLTImmMacro:
2376 case Mips::BLEImmMacro:
2377 case Mips::BGEImmMacro:
2378 case Mips::BGTImmMacro:
2379 case Mips::BLTUImmMacro:
2380 case Mips::BLEUImmMacro:
2381 case Mips::BGEUImmMacro:
2382 case Mips::BGTUImmMacro:
2383 case Mips::BLTLImmMacro:
2384 case Mips::BLELImmMacro:
2385 case Mips::BGELImmMacro:
2386 case Mips::BGTLImmMacro:
2387 case Mips::BLTULImmMacro:
2388 case Mips::BLEULImmMacro:
2389 case Mips::BGEULImmMacro:
2390 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002391 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002392 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002393 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002394 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2395 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002396 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002397 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002398 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2399 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002400 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002401 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002402 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2403 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002404 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002405 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002406 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2407 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002408 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002409 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2410 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002411 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002412 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002413 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002414 case Mips::PseudoTRUNC_W_D:
2415 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2416 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002417
2418 case Mips::LoadImmSingleGPR:
2419 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2420 ? MER_Fail
2421 : MER_Success;
2422 case Mips::LoadImmSingleFGR:
2423 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2424 ? MER_Fail
2425 : MER_Success;
2426 case Mips::LoadImmDoubleGPR:
2427 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2428 ? MER_Fail
2429 : MER_Success;
2430 case Mips::LoadImmDoubleFGR:
2431 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2432 ? MER_Fail
2433 : MER_Success;
2434 case Mips::LoadImmDoubleFGR_32:
2435 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2436 ? MER_Fail
2437 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002438 case Mips::Ulh:
2439 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2440 case Mips::Ulhu:
2441 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002442 case Mips::Ush:
2443 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002444 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002445 case Mips::Usw:
2446 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002447 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002448 case Mips::NORImm64:
2449 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2450 case Mips::SLTImm64:
2451 if (isInt<16>(Inst.getOperand(2).getImm())) {
2452 Inst.setOpcode(Mips::SLTi64);
2453 return MER_NotAMacro;
2454 }
2455 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2456 case Mips::SLTUImm64:
2457 if (isInt<16>(Inst.getOperand(2).getImm())) {
2458 Inst.setOpcode(Mips::SLTiu64);
2459 return MER_NotAMacro;
2460 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002461 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002462 case Mips::ADDi: case Mips::ADDi_MM:
2463 case Mips::ADDiu: case Mips::ADDiu_MM:
2464 case Mips::SLTi: case Mips::SLTi_MM:
2465 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002466 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2467 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2468 int64_t ImmValue = Inst.getOperand(2).getImm();
2469 if (isInt<16>(ImmValue))
2470 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002471 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2472 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002473 }
2474 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002475 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2476 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2477 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002478 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2479 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2480 int64_t ImmValue = Inst.getOperand(2).getImm();
2481 if (isUInt<16>(ImmValue))
2482 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002483 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2484 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002485 }
2486 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002487 case Mips::ROL:
2488 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002489 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002490 case Mips::ROLImm:
2491 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002492 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002493 case Mips::DROL:
2494 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002495 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002496 case Mips::DROLImm:
2497 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002498 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002499 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002500 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002501 case Mips::MULImmMacro:
2502 case Mips::DMULImmMacro:
2503 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2504 case Mips::MULOMacro:
2505 case Mips::DMULOMacro:
2506 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2507 case Mips::MULOUMacro:
2508 case Mips::DMULOUMacro:
2509 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2510 case Mips::DMULMacro:
2511 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002512 case Mips::LDMacro:
2513 case Mips::SDMacro:
2514 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2515 Inst.getOpcode() == Mips::LDMacro)
2516 ? MER_Fail
2517 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002518 case Mips::SEQMacro:
2519 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2520 case Mips::SEQIMacro:
2521 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002522 case Mips::MFTC0: case Mips::MTTC0:
2523 case Mips::MFTGPR: case Mips::MTTGPR:
2524 case Mips::MFTLO: case Mips::MTTLO:
2525 case Mips::MFTHI: case Mips::MTTHI:
2526 case Mips::MFTACX: case Mips::MTTACX:
2527 case Mips::MFTDSP: case Mips::MTTDSP:
2528 case Mips::MFTC1: case Mips::MTTC1:
2529 case Mips::MFTHC1: case Mips::MTTHC1:
2530 case Mips::CFTC1: case Mips::CTTC1:
2531 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002532 }
Jack Carter30a59822012-10-04 04:03:53 +00002533}
Jack Carter92995f12012-10-06 00:53:28 +00002534
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002535bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002536 MCStreamer &Out,
2537 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002538 MipsTargetStreamer &TOut = getTargetStreamer();
2539
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002540 // Create a JALR instruction which is going to replace the pseudo-JAL.
2541 MCInst JalrInst;
2542 JalrInst.setLoc(IDLoc);
2543 const MCOperand FirstRegOp = Inst.getOperand(0);
2544 const unsigned Opcode = Inst.getOpcode();
2545
2546 if (Opcode == Mips::JalOneReg) {
2547 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002548 if (IsCpRestoreSet && inMicroMipsMode()) {
2549 JalrInst.setOpcode(Mips::JALRS16_MM);
2550 JalrInst.addOperand(FirstRegOp);
2551 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002552 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002553 JalrInst.addOperand(FirstRegOp);
2554 } else {
2555 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002556 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002557 JalrInst.addOperand(FirstRegOp);
2558 }
2559 } else if (Opcode == Mips::JalTwoReg) {
2560 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002561 if (IsCpRestoreSet && inMicroMipsMode())
2562 JalrInst.setOpcode(Mips::JALRS_MM);
2563 else
2564 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002565 JalrInst.addOperand(FirstRegOp);
2566 const MCOperand SecondRegOp = Inst.getOperand(1);
2567 JalrInst.addOperand(SecondRegOp);
2568 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002569 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002570
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002571 // If .set reorder is active and branch instruction has a delay slot,
2572 // emit a NOP after it.
2573 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002574 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2575 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2576 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002577
2578 return false;
2579}
2580
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002581/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002582template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002583 unsigned BitNum = findFirstSet(x);
2584
2585 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2586}
2587
2588/// Load (or add) an immediate into a register.
2589///
2590/// @param ImmValue The immediate to load.
2591/// @param DstReg The register that will hold the immediate.
2592/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2593/// for a simple initialization.
2594/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2595/// @param IsAddress True if the immediate represents an address. False if it
2596/// is an integer.
2597/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002598bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002599 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002600 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2601 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002602 MipsTargetStreamer &TOut = getTargetStreamer();
2603
Toma Tabacu00e98672015-05-01 12:19:27 +00002604 if (!Is32BitImm && !isGP64bit()) {
2605 Error(IDLoc, "instruction requires a 64-bit architecture");
2606 return true;
2607 }
2608
Daniel Sanders03f9c012015-07-14 12:24:22 +00002609 if (Is32BitImm) {
2610 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2611 // Sign extend up to 64-bit so that the predicates match the hardware
2612 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2613 // true.
2614 ImmValue = SignExtend64<32>(ImmValue);
2615 } else {
2616 Error(IDLoc, "instruction requires a 32-bit immediate");
2617 return true;
2618 }
2619 }
2620
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002621 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2622 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2623
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002624 bool UseSrcReg = false;
2625 if (SrcReg != Mips::NoRegister)
2626 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002627
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002628 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002629 if (UseSrcReg &&
2630 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002631 // At this point we need AT to perform the expansions and we exit if it is
2632 // not available.
2633 unsigned ATReg = getATReg(IDLoc);
2634 if (!ATReg)
2635 return true;
2636 TmpReg = ATReg;
2637 }
2638
Daniel Sanders03f9c012015-07-14 12:24:22 +00002639 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002640 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002641 SrcReg = ZeroReg;
2642
2643 // This doesn't quite follow the usual ABI expectations for N32 but matches
2644 // traditional assembler behaviour. N32 would normally use addiu for both
2645 // integers and addresses.
2646 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002647 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002648 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002649 }
2650
Daniel Sandersa736b372016-04-29 13:33:12 +00002651 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002652 return false;
2653 }
2654
2655 if (isUInt<16>(ImmValue)) {
2656 unsigned TmpReg = DstReg;
2657 if (SrcReg == DstReg) {
2658 TmpReg = getATReg(IDLoc);
2659 if (!TmpReg)
2660 return true;
2661 }
2662
Daniel Sandersa736b372016-04-29 13:33:12 +00002663 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002664 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002665 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002666 return false;
2667 }
2668
2669 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002670 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002671
Toma Tabacu79588102015-04-29 10:19:56 +00002672 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2673 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002674 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002675 // Traditional behaviour seems to special case this particular value. It's
2676 // not clear why other masks are handled differently.
2677 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002678 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2679 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002680 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002681 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002682 return false;
2683 }
2684
2685 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002686 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002687 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2688 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002689 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002690 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002691 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002692 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002693 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002694 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002695
Daniel Sandersa736b372016-04-29 13:33:12 +00002696 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002697 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002698 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002699 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002700 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002701 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002702 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002703
2704 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2705 if (Is32BitImm) {
2706 Error(IDLoc, "instruction requires a 32-bit immediate");
2707 return true;
2708 }
2709
2710 // Traditionally, these immediates are shifted as little as possible and as
2711 // such we align the most significant bit to bit 15 of our temporary.
2712 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2713 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2714 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2715 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002716 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2717 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002718
2719 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002720 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002721
2722 return false;
2723 }
2724
2725 warnIfNoMacro(IDLoc);
2726
2727 // The remaining case is packed with a sequence of dsll and ori with zeros
2728 // being omitted and any neighbouring dsll's being coalesced.
2729 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2730
2731 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2732 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002733 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002734 return false;
2735
2736 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2737 // skip it and defer the shift to the next chunk.
2738 unsigned ShiftCarriedForwards = 16;
2739 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2740 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2741
2742 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002743 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2744 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002745 ShiftCarriedForwards = 0;
2746 }
2747
2748 ShiftCarriedForwards += 16;
2749 }
2750 ShiftCarriedForwards -= 16;
2751
2752 // Finish any remaining shifts left by trailing zeros.
2753 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002754 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002755
2756 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002757 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002758
Matheus Almeida3813d572014-06-19 14:39:14 +00002759 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002760}
Jack Carter92995f12012-10-06 00:53:28 +00002761
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002762bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002763 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002764 const MCOperand &ImmOp = Inst.getOperand(1);
2765 assert(ImmOp.isImm() && "expected immediate operand kind");
2766 const MCOperand &DstRegOp = Inst.getOperand(0);
2767 assert(DstRegOp.isReg() && "expected register operand kind");
2768
2769 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002770 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002771 return true;
2772
2773 return false;
2774}
2775
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002776bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2777 const MCOperand &Offset,
2778 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002779 MCStreamer &Out,
2780 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002781 // la can't produce a usable address when addresses are 64-bit.
2782 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2783 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2784 // We currently can't do this because we depend on the equality
2785 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2786 Error(IDLoc, "la used to load 64-bit address");
2787 // Continue as if we had 'dla' instead.
2788 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002789 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002790 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002791
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002792 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002793 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002794 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002795 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002796 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002797
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002798 if (!Offset.isImm())
2799 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002800 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002801
Scott Egerton24557012016-01-21 15:11:01 +00002802 if (!ABI.ArePtrs64bit()) {
2803 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2804 Is32BitAddress = true;
2805 }
2806
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002807 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002808 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002809}
2810
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002811bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2812 unsigned DstReg, unsigned SrcReg,
2813 bool Is32BitSym, SMLoc IDLoc,
2814 MCStreamer &Out,
2815 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002816 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002817 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002818 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002819 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002820
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002821 if (inPicMode() && ABI.IsO32()) {
2822 MCValue Res;
2823 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2824 Error(IDLoc, "expected relocatable expression");
2825 return true;
2826 }
2827 if (Res.getSymB() != nullptr) {
2828 Error(IDLoc, "expected relocatable expression with only one symbol");
2829 return true;
2830 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002831
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002832 // The case where the result register is $25 is somewhat special. If the
2833 // symbol in the final relocation is external and not modified with a
2834 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2835 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002836 Res.getConstant() == 0 &&
2837 !(Res.getSymA()->getSymbol().isInSection() ||
2838 Res.getSymA()->getSymbol().isTemporary() ||
2839 (Res.getSymA()->getSymbol().isELF() &&
2840 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2841 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002842 const MCExpr *CallExpr =
2843 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2844 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2845 MCOperand::createExpr(CallExpr), IDLoc, STI);
2846 return false;
2847 }
2848
2849 // The remaining cases are:
2850 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2851 // >addiu $tmp, $tmp, %lo(offset)
2852 // >addiu $rd, $tmp, $rs
2853 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2854 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2855 // >addiu $rd, $tmp, $rs
2856 // The addiu's marked with a '>' may be omitted if they are redundant. If
2857 // this happens then the last instruction must use $rd as the result
2858 // register.
2859 const MipsMCExpr *GotExpr =
2860 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2861 const MCExpr *LoExpr = nullptr;
2862 if (Res.getSymA()->getSymbol().isInSection() ||
2863 Res.getSymA()->getSymbol().isTemporary())
2864 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2865 else if (Res.getConstant() != 0) {
2866 // External symbols fully resolve the symbol with just the %got(symbol)
2867 // but we must still account for any offset to the symbol for expressions
2868 // like symbol+8.
2869 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2870 }
2871
2872 unsigned TmpReg = DstReg;
2873 if (UseSrcReg &&
2874 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2875 SrcReg)) {
2876 // If $rs is the same as $rd, we need to use AT.
2877 // If it is not available we exit.
2878 unsigned ATReg = getATReg(IDLoc);
2879 if (!ATReg)
2880 return true;
2881 TmpReg = ATReg;
2882 }
2883
2884 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2885 MCOperand::createExpr(GotExpr), IDLoc, STI);
2886
2887 if (LoExpr)
2888 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2889 IDLoc, STI);
2890
2891 if (UseSrcReg)
2892 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2893
2894 return false;
2895 }
2896
Simon Dardisda96c432017-06-30 15:44:27 +00002897 if (inPicMode() && ABI.ArePtrs64bit()) {
2898 MCValue Res;
2899 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2900 Error(IDLoc, "expected relocatable expression");
2901 return true;
2902 }
2903 if (Res.getSymB() != nullptr) {
2904 Error(IDLoc, "expected relocatable expression with only one symbol");
2905 return true;
2906 }
2907
2908 // The case where the result register is $25 is somewhat special. If the
2909 // symbol in the final relocation is external and not modified with a
2910 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2911 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2912 Res.getConstant() == 0 &&
2913 !(Res.getSymA()->getSymbol().isInSection() ||
2914 Res.getSymA()->getSymbol().isTemporary() ||
2915 (Res.getSymA()->getSymbol().isELF() &&
2916 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2917 ELF::STB_LOCAL))) {
2918 const MCExpr *CallExpr =
2919 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2920 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2921 MCOperand::createExpr(CallExpr), IDLoc, STI);
2922 return false;
2923 }
2924
2925 // The remaining cases are:
2926 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2927 // >daddiu $tmp, $tmp, offset
2928 // >daddu $rd, $tmp, $rs
2929 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2930 // this happens then the last instruction must use $rd as the result
2931 // register.
2932 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2933 Res.getSymA(),
2934 getContext());
2935 const MCExpr *LoExpr = nullptr;
2936 if (Res.getConstant() != 0) {
2937 // Symbols fully resolve with just the %got_disp(symbol) but we
2938 // must still account for any offset to the symbol for
2939 // expressions like symbol+8.
2940 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2941
2942 // FIXME: Offsets greater than 16 bits are not yet implemented.
2943 // FIXME: The correct range is a 32-bit sign-extended number.
2944 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2945 Error(IDLoc, "macro instruction uses large offset, which is not "
2946 "currently supported");
2947 return true;
2948 }
2949 }
2950
2951 unsigned TmpReg = DstReg;
2952 if (UseSrcReg &&
2953 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2954 SrcReg)) {
2955 // If $rs is the same as $rd, we need to use AT.
2956 // If it is not available we exit.
2957 unsigned ATReg = getATReg(IDLoc);
2958 if (!ATReg)
2959 return true;
2960 TmpReg = ATReg;
2961 }
2962
2963 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2964 MCOperand::createExpr(GotExpr), IDLoc, STI);
2965
2966 if (LoExpr)
2967 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2968 IDLoc, STI);
2969
2970 if (UseSrcReg)
2971 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2972
2973 return false;
2974 }
2975
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002976 const MipsMCExpr *HiExpr =
2977 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2978 const MipsMCExpr *LoExpr =
2979 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002980
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002981 // This is the 64-bit symbol address expansion.
2982 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002983 // We need AT for the 64-bit expansion in the cases where the optional
2984 // source register is the destination register and for the superscalar
2985 // scheduled form.
2986 //
2987 // If it is not available we exit if the destination is the same as the
2988 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002989
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002990 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002991 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002992 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002993 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002994
Simon Dardis3aa8a902017-02-06 12:43:46 +00002995 bool RdRegIsRsReg =
2996 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2997
2998 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2999 unsigned ATReg = getATReg(IDLoc);
3000
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003001 // If $rs is the same as $rd:
3002 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3003 // daddiu $at, $at, %higher(sym)
3004 // dsll $at, $at, 16
3005 // daddiu $at, $at, %hi(sym)
3006 // dsll $at, $at, 16
3007 // daddiu $at, $at, %lo(sym)
3008 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003009 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3010 STI);
3011 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3012 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3013 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3014 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3015 IDLoc, STI);
3016 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3017 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3018 IDLoc, STI);
3019 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003020
3021 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003022 } else if (canUseATReg() && !RdRegIsRsReg) {
3023 unsigned ATReg = getATReg(IDLoc);
3024
3025 // If the $rs is different from $rd or if $rs isn't specified and we
3026 // have $at available:
3027 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3028 // lui $at, %hi(sym)
3029 // daddiu $rd, $rd, %higher(sym)
3030 // daddiu $at, $at, %lo(sym)
3031 // dsll32 $rd, $rd, 0
3032 // daddu $rd, $rd, $at
3033 // (daddu $rd, $rd, $rs)
3034 //
3035 // Which is preferred for superscalar issue.
3036 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3037 STI);
3038 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3039 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3040 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3041 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3042 IDLoc, STI);
3043 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3044 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3045 if (UseSrcReg)
3046 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3047
3048 return false;
3049 } else if (!canUseATReg() && !RdRegIsRsReg) {
3050 // Otherwise, synthesize the address in the destination register
3051 // serially:
3052 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3053 // daddiu $rd, $rd, %higher(sym)
3054 // dsll $rd, $rd, 16
3055 // daddiu $rd, $rd, %hi(sym)
3056 // dsll $rd, $rd, 16
3057 // daddiu $rd, $rd, %lo(sym)
3058 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3059 STI);
3060 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3061 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3062 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3063 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3064 MCOperand::createExpr(HiExpr), IDLoc, STI);
3065 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3066 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3067 MCOperand::createExpr(LoExpr), IDLoc, STI);
3068 if (UseSrcReg)
3069 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3070
3071 return false;
3072 } else {
3073 // We have a case where SrcReg == DstReg and we don't have $at
3074 // available. We can't expand this case, so error out appropriately.
3075 assert(SrcReg == DstReg && !canUseATReg() &&
3076 "Could have expanded dla but didn't?");
3077 reportParseError(IDLoc,
3078 "pseudo-instruction requires $at, which is not available");
3079 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003080 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003081 }
3082
3083 // And now, the 32-bit symbol address expansion:
3084 // If $rs is the same as $rd:
3085 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3086 // ori $at, $at, %lo(sym)
3087 // addu $rd, $at, $rd
3088 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3089 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3090 // ori $rd, $rd, %lo(sym)
3091 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003092 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003093 if (UseSrcReg &&
3094 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003095 // If $rs is the same as $rd, we need to use AT.
3096 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003097 unsigned ATReg = getATReg(IDLoc);
3098 if (!ATReg)
3099 return true;
3100 TmpReg = ATReg;
3101 }
3102
Daniel Sandersa736b372016-04-29 13:33:12 +00003103 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3104 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3105 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003106
Toma Tabacufb9d1252015-06-22 12:08:39 +00003107 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003108 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003109 else
Scott Egerton24557012016-01-21 15:11:01 +00003110 assert(
3111 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003112
Toma Tabacu674825c2015-06-16 12:16:24 +00003113 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003114}
3115
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003116// Each double-precision register DO-D15 overlaps with two of the single
3117// precision registers F0-F31. As an example, all of the following hold true:
3118// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3119static unsigned nextReg(unsigned Reg) {
3120 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3121 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3122 switch (Reg) {
3123 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3124 case Mips::ZERO: return Mips::AT;
3125 case Mips::AT: return Mips::V0;
3126 case Mips::V0: return Mips::V1;
3127 case Mips::V1: return Mips::A0;
3128 case Mips::A0: return Mips::A1;
3129 case Mips::A1: return Mips::A2;
3130 case Mips::A2: return Mips::A3;
3131 case Mips::A3: return Mips::T0;
3132 case Mips::T0: return Mips::T1;
3133 case Mips::T1: return Mips::T2;
3134 case Mips::T2: return Mips::T3;
3135 case Mips::T3: return Mips::T4;
3136 case Mips::T4: return Mips::T5;
3137 case Mips::T5: return Mips::T6;
3138 case Mips::T6: return Mips::T7;
3139 case Mips::T7: return Mips::S0;
3140 case Mips::S0: return Mips::S1;
3141 case Mips::S1: return Mips::S2;
3142 case Mips::S2: return Mips::S3;
3143 case Mips::S3: return Mips::S4;
3144 case Mips::S4: return Mips::S5;
3145 case Mips::S5: return Mips::S6;
3146 case Mips::S6: return Mips::S7;
3147 case Mips::S7: return Mips::T8;
3148 case Mips::T8: return Mips::T9;
3149 case Mips::T9: return Mips::K0;
3150 case Mips::K0: return Mips::K1;
3151 case Mips::K1: return Mips::GP;
3152 case Mips::GP: return Mips::SP;
3153 case Mips::SP: return Mips::FP;
3154 case Mips::FP: return Mips::RA;
3155 case Mips::RA: return Mips::ZERO;
3156 case Mips::D0: return Mips::F1;
3157 case Mips::D1: return Mips::F3;
3158 case Mips::D2: return Mips::F5;
3159 case Mips::D3: return Mips::F7;
3160 case Mips::D4: return Mips::F9;
3161 case Mips::D5: return Mips::F11;
3162 case Mips::D6: return Mips::F13;
3163 case Mips::D7: return Mips::F15;
3164 case Mips::D8: return Mips::F17;
3165 case Mips::D9: return Mips::F19;
3166 case Mips::D10: return Mips::F21;
3167 case Mips::D11: return Mips::F23;
3168 case Mips::D12: return Mips::F25;
3169 case Mips::D13: return Mips::F27;
3170 case Mips::D14: return Mips::F29;
3171 case Mips::D15: return Mips::F31;
3172 }
3173}
3174
3175// FIXME: This method is too general. In principle we should compute the number
3176// of instructions required to synthesize the immediate inline compared to
3177// synthesizing the address inline and relying on non .text sections.
3178// For static O32 and N32 this may yield a small benefit, for static N64 this is
3179// likely to yield a much larger benefit as we have to synthesize a 64bit
3180// address to load a 64 bit value.
3181bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3182 MCSymbol *Sym) {
3183 unsigned ATReg = getATReg(IDLoc);
3184 if (!ATReg)
3185 return true;
3186
3187 if(IsPicEnabled) {
3188 const MCExpr *GotSym =
3189 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3190 const MipsMCExpr *GotExpr =
3191 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3192
3193 if(isABI_O32() || isABI_N32()) {
3194 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3195 IDLoc, STI);
3196 } else { //isABI_N64()
3197 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3198 IDLoc, STI);
3199 }
3200 } else { //!IsPicEnabled
3201 const MCExpr *HiSym =
3202 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3203 const MipsMCExpr *HiExpr =
3204 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3205
3206 // FIXME: This is technically correct but gives a different result to gas,
3207 // but gas is incomplete there (it has a fixme noting it doesn't work with
3208 // 64-bit addresses).
3209 // FIXME: With -msym32 option, the address expansion for N64 should probably
3210 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3211 // symbol's value is considered sign extended.
3212 if(isABI_O32() || isABI_N32()) {
3213 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3214 } else { //isABI_N64()
3215 const MCExpr *HighestSym =
3216 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3217 const MipsMCExpr *HighestExpr =
3218 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3219 const MCExpr *HigherSym =
3220 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3221 const MipsMCExpr *HigherExpr =
3222 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3223
3224 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3225 STI);
3226 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3227 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3228 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3229 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3230 IDLoc, STI);
3231 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3232 }
3233 }
3234 return false;
3235}
3236
3237bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3238 bool Is64FPU, SMLoc IDLoc,
3239 MCStreamer &Out,
3240 const MCSubtargetInfo *STI) {
3241 MipsTargetStreamer &TOut = getTargetStreamer();
3242 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3243 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3244 "Invalid instruction operand.");
3245
3246 unsigned FirstReg = Inst.getOperand(0).getReg();
3247 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3248
3249 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3250 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3251 // exponent field), convert it to double (e.g. 1 to 1.0)
3252 if ((HiImmOp64 & 0x7ff00000) == 0) {
3253 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3254 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3255 }
3256
3257 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3258 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3259
3260 if (IsSingle) {
3261 // Conversion of a double in an uint64_t to a float in a uint32_t,
3262 // retaining the bit pattern of a float.
3263 uint32_t ImmOp32;
3264 double doubleImm = BitsToDouble(ImmOp64);
3265 float tmp_float = static_cast<float>(doubleImm);
3266 ImmOp32 = FloatToBits(tmp_float);
3267
3268 if (IsGPR) {
3269 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3270 Out, STI))
3271 return true;
3272 return false;
3273 } else {
3274 unsigned ATReg = getATReg(IDLoc);
3275 if (!ATReg)
3276 return true;
3277 if (LoImmOp64 == 0) {
3278 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3279 Out, STI))
3280 return true;
3281 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3282 return false;
3283 }
3284
3285 MCSection *CS = getStreamer().getCurrentSectionOnly();
3286 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3287 // where appropriate.
3288 MCSection *ReadOnlySection = getContext().getELFSection(
3289 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3290
3291 MCSymbol *Sym = getContext().createTempSymbol();
3292 const MCExpr *LoSym =
3293 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3294 const MipsMCExpr *LoExpr =
3295 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3296
3297 getStreamer().SwitchSection(ReadOnlySection);
3298 getStreamer().EmitLabel(Sym, IDLoc);
3299 getStreamer().EmitIntValue(ImmOp32, 4);
3300 getStreamer().SwitchSection(CS);
3301
3302 if(emitPartialAddress(TOut, IDLoc, Sym))
3303 return true;
3304 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3305 MCOperand::createExpr(LoExpr), IDLoc, STI);
3306 }
3307 return false;
3308 }
3309
3310 // if(!IsSingle)
3311 unsigned ATReg = getATReg(IDLoc);
3312 if (!ATReg)
3313 return true;
3314
3315 if (IsGPR) {
3316 if (LoImmOp64 == 0) {
3317 if(isABI_N32() || isABI_N64()) {
3318 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3319 IDLoc, Out, STI))
3320 return true;
3321 return false;
3322 } else {
3323 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3324 IDLoc, Out, STI))
3325 return true;
3326
3327 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3328 IDLoc, Out, STI))
3329 return true;
3330 return false;
3331 }
3332 }
3333
3334 MCSection *CS = getStreamer().getCurrentSectionOnly();
3335 MCSection *ReadOnlySection = getContext().getELFSection(
3336 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3337
3338 MCSymbol *Sym = getContext().createTempSymbol();
3339 const MCExpr *LoSym =
3340 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3341 const MipsMCExpr *LoExpr =
3342 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3343
3344 getStreamer().SwitchSection(ReadOnlySection);
3345 getStreamer().EmitLabel(Sym, IDLoc);
3346 getStreamer().EmitIntValue(HiImmOp64, 4);
3347 getStreamer().EmitIntValue(LoImmOp64, 4);
3348 getStreamer().SwitchSection(CS);
3349
3350 if(emitPartialAddress(TOut, IDLoc, Sym))
3351 return true;
3352 if(isABI_N64())
3353 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3354 MCOperand::createExpr(LoExpr), IDLoc, STI);
3355 else
3356 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3357 MCOperand::createExpr(LoExpr), IDLoc, STI);
3358
3359 if(isABI_N32() || isABI_N64())
3360 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3361 else {
3362 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3363 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3364 }
3365 return false;
3366 } else { // if(!IsGPR && !IsSingle)
3367 if ((LoImmOp64 == 0) &&
3368 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3369 // FIXME: In the case where the constant is zero, we can load the
3370 // register directly from the zero register.
3371 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3372 Out, STI))
3373 return true;
3374 if (isABI_N32() || isABI_N64())
3375 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3376 else if (hasMips32r2()) {
3377 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3378 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3379 } else {
3380 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3381 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3382 }
3383 return false;
3384 }
3385
3386 MCSection *CS = getStreamer().getCurrentSectionOnly();
3387 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3388 // where appropriate.
3389 MCSection *ReadOnlySection = getContext().getELFSection(
3390 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3391
3392 MCSymbol *Sym = getContext().createTempSymbol();
3393 const MCExpr *LoSym =
3394 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3395 const MipsMCExpr *LoExpr =
3396 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3397
3398 getStreamer().SwitchSection(ReadOnlySection);
3399 getStreamer().EmitLabel(Sym, IDLoc);
3400 getStreamer().EmitIntValue(HiImmOp64, 4);
3401 getStreamer().EmitIntValue(LoImmOp64, 4);
3402 getStreamer().SwitchSection(CS);
3403
3404 if(emitPartialAddress(TOut, IDLoc, Sym))
3405 return true;
3406 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3407 MCOperand::createExpr(LoExpr), IDLoc, STI);
3408 }
3409 return false;
3410}
3411
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003412bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3413 MCStreamer &Out,
3414 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003415 MipsTargetStreamer &TOut = getTargetStreamer();
3416
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003417 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3418 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003419
3420 MCOperand Offset = Inst.getOperand(0);
3421 if (Offset.isExpr()) {
3422 Inst.clear();
3423 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003424 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3425 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3426 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003427 } else {
3428 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003429 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003430 // If offset fits into 11 bits then this instruction becomes microMIPS
3431 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003432 if (inMicroMipsMode())
3433 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003434 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003435 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003436 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003437 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003438 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003439 Inst.clear();
3440 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003441 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3442 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3443 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003444 }
3445 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003446 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003447
Zoran Jovanovicada70912015-09-07 11:56:37 +00003448 // If .set reorder is active and branch instruction has a delay slot,
3449 // emit a NOP after it.
3450 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3451 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003452 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003453
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003454 return false;
3455}
3456
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003457bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3458 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003459 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003460 const MCOperand &DstRegOp = Inst.getOperand(0);
3461 assert(DstRegOp.isReg() && "expected register operand kind");
3462
3463 const MCOperand &ImmOp = Inst.getOperand(1);
3464 assert(ImmOp.isImm() && "expected immediate operand kind");
3465
3466 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003467 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3468 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003469
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003470 bool IsLikely = false;
3471
Toma Tabacue1e460d2015-06-11 10:36:10 +00003472 unsigned OpCode = 0;
3473 switch(Inst.getOpcode()) {
3474 case Mips::BneImm:
3475 OpCode = Mips::BNE;
3476 break;
3477 case Mips::BeqImm:
3478 OpCode = Mips::BEQ;
3479 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003480 case Mips::BEQLImmMacro:
3481 OpCode = Mips::BEQL;
3482 IsLikely = true;
3483 break;
3484 case Mips::BNELImmMacro:
3485 OpCode = Mips::BNEL;
3486 IsLikely = true;
3487 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003488 default:
3489 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3490 break;
3491 }
3492
3493 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003494 if (ImmValue == 0) {
3495 if (IsLikely) {
3496 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3497 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3498 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3499 } else
3500 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3501 STI);
3502 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003503 warnIfNoMacro(IDLoc);
3504
3505 unsigned ATReg = getATReg(IDLoc);
3506 if (!ATReg)
3507 return true;
3508
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003509 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003510 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003511 return true;
3512
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003513 if (IsLikely) {
3514 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3515 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3516 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3517 } else
3518 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003519 }
3520 return false;
3521}
3522
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003523void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003524 const MCSubtargetInfo *STI, bool IsLoad,
3525 bool IsImmOpnd) {
3526 if (IsLoad) {
3527 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3528 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003529 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003530 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3531}
3532
3533void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3534 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3535 MipsTargetStreamer &TOut = getTargetStreamer();
3536
3537 unsigned DstReg = Inst.getOperand(0).getReg();
3538 unsigned BaseReg = Inst.getOperand(1).getReg();
3539
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003540 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003541 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3542 unsigned DstRegClassID =
3543 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3544 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3545 (DstRegClassID == Mips::GPR64RegClassID);
3546
3547 if (IsImmOpnd) {
3548 // Try to use DstReg as the temporary.
3549 if (IsGPR && (BaseReg != DstReg)) {
3550 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3551 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3552 STI);
3553 return;
3554 }
3555
Matheus Almeida7de68e72014-06-18 14:46:05 +00003556 // At this point we need AT to perform the expansions and we exit if it is
3557 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003558 unsigned ATReg = getATReg(IDLoc);
3559 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003560 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003561
3562 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3563 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3564 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003565 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003566
Daniel Sandersfba875f2016-04-29 13:43:45 +00003567 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003568 MCOperand LoOperand = MCOperand::createExpr(
3569 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3570 MCOperand HiOperand = MCOperand::createExpr(
3571 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003572
3573 // Try to use DstReg as the temporary.
3574 if (IsGPR && (BaseReg != DstReg)) {
3575 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3576 LoOperand, DstReg, IDLoc, STI);
3577 return;
3578 }
3579
3580 // At this point we need AT to perform the expansions and we exit if it is
3581 // not available.
3582 unsigned ATReg = getATReg(IDLoc);
3583 if (!ATReg)
3584 return;
3585
3586 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3587 LoOperand, ATReg, IDLoc, STI);
3588}
3589
3590void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3591 const MCSubtargetInfo *STI,
3592 bool IsImmOpnd) {
3593 MipsTargetStreamer &TOut = getTargetStreamer();
3594
3595 unsigned SrcReg = Inst.getOperand(0).getReg();
3596 unsigned BaseReg = Inst.getOperand(1).getReg();
3597
Daniel Sanders241c6792016-05-12 14:01:50 +00003598 if (IsImmOpnd) {
3599 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3600 Inst.getOperand(2).getImm(),
3601 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3602 return;
3603 }
3604
Daniel Sandersfba875f2016-04-29 13:43:45 +00003605 unsigned ATReg = getATReg(IDLoc);
3606 if (!ATReg)
3607 return;
3608
Daniel Sandersfba875f2016-04-29 13:43:45 +00003609 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003610 MCOperand LoOperand = MCOperand::createExpr(
3611 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3612 MCOperand HiOperand = MCOperand::createExpr(
3613 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003614 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3615 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003616}
3617
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003618bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3619 MCStreamer &Out,
3620 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003621 unsigned OpNum = Inst.getNumOperands();
3622 unsigned Opcode = Inst.getOpcode();
3623 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3624
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003625 assert(Inst.getOperand(OpNum - 1).isImm() &&
3626 Inst.getOperand(OpNum - 2).isReg() &&
3627 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003628
3629 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3630 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003631 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3632 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3633 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3634 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003635 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003636 if (inMicroMipsMode() && hasMips32r6())
3637 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3638 else
3639 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3640 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003641
3642 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003643 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003644 return false;
3645}
3646
Toma Tabacu1a108322015-06-17 13:20:24 +00003647bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003648 MCStreamer &Out,
3649 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003650 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003651 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003652 unsigned PseudoOpcode = Inst.getOpcode();
3653 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003654 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003655 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3656
3657 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003658 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003659
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003660 unsigned TrgReg;
3661 if (TrgOp.isReg())
3662 TrgReg = TrgOp.getReg();
3663 else if (TrgOp.isImm()) {
3664 warnIfNoMacro(IDLoc);
3665 EmittedNoMacroWarning = true;
3666
3667 TrgReg = getATReg(IDLoc);
3668 if (!TrgReg)
3669 return true;
3670
3671 switch(PseudoOpcode) {
3672 default:
3673 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3674 case Mips::BLTImmMacro:
3675 PseudoOpcode = Mips::BLT;
3676 break;
3677 case Mips::BLEImmMacro:
3678 PseudoOpcode = Mips::BLE;
3679 break;
3680 case Mips::BGEImmMacro:
3681 PseudoOpcode = Mips::BGE;
3682 break;
3683 case Mips::BGTImmMacro:
3684 PseudoOpcode = Mips::BGT;
3685 break;
3686 case Mips::BLTUImmMacro:
3687 PseudoOpcode = Mips::BLTU;
3688 break;
3689 case Mips::BLEUImmMacro:
3690 PseudoOpcode = Mips::BLEU;
3691 break;
3692 case Mips::BGEUImmMacro:
3693 PseudoOpcode = Mips::BGEU;
3694 break;
3695 case Mips::BGTUImmMacro:
3696 PseudoOpcode = Mips::BGTU;
3697 break;
3698 case Mips::BLTLImmMacro:
3699 PseudoOpcode = Mips::BLTL;
3700 break;
3701 case Mips::BLELImmMacro:
3702 PseudoOpcode = Mips::BLEL;
3703 break;
3704 case Mips::BGELImmMacro:
3705 PseudoOpcode = Mips::BGEL;
3706 break;
3707 case Mips::BGTLImmMacro:
3708 PseudoOpcode = Mips::BGTL;
3709 break;
3710 case Mips::BLTULImmMacro:
3711 PseudoOpcode = Mips::BLTUL;
3712 break;
3713 case Mips::BLEULImmMacro:
3714 PseudoOpcode = Mips::BLEUL;
3715 break;
3716 case Mips::BGEULImmMacro:
3717 PseudoOpcode = Mips::BGEUL;
3718 break;
3719 case Mips::BGTULImmMacro:
3720 PseudoOpcode = Mips::BGTUL;
3721 break;
3722 }
3723
3724 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003725 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003726 return true;
3727 }
3728
Toma Tabacu1a108322015-06-17 13:20:24 +00003729 switch (PseudoOpcode) {
3730 case Mips::BLT:
3731 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003732 case Mips::BLTL:
3733 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003734 AcceptsEquality = false;
3735 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003736 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3737 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003738 ZeroSrcOpcode = Mips::BGTZ;
3739 ZeroTrgOpcode = Mips::BLTZ;
3740 break;
3741 case Mips::BLE:
3742 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003743 case Mips::BLEL:
3744 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003745 AcceptsEquality = true;
3746 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003747 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3748 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003749 ZeroSrcOpcode = Mips::BGEZ;
3750 ZeroTrgOpcode = Mips::BLEZ;
3751 break;
3752 case Mips::BGE:
3753 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003754 case Mips::BGEL:
3755 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003756 AcceptsEquality = true;
3757 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003758 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3759 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003760 ZeroSrcOpcode = Mips::BLEZ;
3761 ZeroTrgOpcode = Mips::BGEZ;
3762 break;
3763 case Mips::BGT:
3764 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003765 case Mips::BGTL:
3766 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003767 AcceptsEquality = false;
3768 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003769 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3770 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003771 ZeroSrcOpcode = Mips::BLTZ;
3772 ZeroTrgOpcode = Mips::BGTZ;
3773 break;
3774 default:
3775 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3776 }
3777
Toma Tabacu1a108322015-06-17 13:20:24 +00003778 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3779 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3780 if (IsSrcRegZero && IsTrgRegZero) {
3781 // FIXME: All of these Opcode-specific if's are needed for compatibility
3782 // with GAS' behaviour. However, they may not generate the most efficient
3783 // code in some circumstances.
3784 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003785 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3786 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003787 return false;
3788 }
3789 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003790 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3791 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003792 Warning(IDLoc, "branch is always taken");
3793 return false;
3794 }
3795 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003796 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3797 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003798 Warning(IDLoc, "branch is always taken");
3799 return false;
3800 }
3801 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003802 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3803 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003804 return false;
3805 }
3806 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003807 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3808 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003809 return false;
3810 }
3811 if (AcceptsEquality) {
3812 // If both registers are $0 and the pseudo-branch accepts equality, it
3813 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003814 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3815 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003816 Warning(IDLoc, "branch is always taken");
3817 return false;
3818 }
3819 // If both registers are $0 and the pseudo-branch does not accept
3820 // equality, it will never be taken, so we don't have to emit anything.
3821 return false;
3822 }
3823 if (IsSrcRegZero || IsTrgRegZero) {
3824 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3825 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3826 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3827 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3828 // the pseudo-branch will never be taken, so we don't emit anything.
3829 // This only applies to unsigned pseudo-branches.
3830 return false;
3831 }
3832 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3833 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3834 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3835 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3836 // the pseudo-branch will always be taken, so we emit an unconditional
3837 // branch.
3838 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003839 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3840 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003841 Warning(IDLoc, "branch is always taken");
3842 return false;
3843 }
3844 if (IsUnsigned) {
3845 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3846 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3847 // the pseudo-branch will be taken only when the non-zero register is
3848 // different from 0, so we emit a BNEZ.
3849 //
3850 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3851 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3852 // the pseudo-branch will be taken only when the non-zero register is
3853 // equal to 0, so we emit a BEQZ.
3854 //
3855 // Because only BLEU and BGEU branch on equality, we can use the
3856 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003857 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3858 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3859 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003860 return false;
3861 }
3862 // If we have a signed pseudo-branch and one of the registers is $0,
3863 // we can use an appropriate compare-to-zero branch. We select which one
3864 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003865 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3866 IsSrcRegZero ? TrgReg : SrcReg,
3867 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003868 return false;
3869 }
3870
3871 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3872 // expansions. If it is not available, we return.
3873 unsigned ATRegNum = getATReg(IDLoc);
3874 if (!ATRegNum)
3875 return true;
3876
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003877 if (!EmittedNoMacroWarning)
3878 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003879
3880 // SLT fits well with 2 of our 4 pseudo-branches:
3881 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3882 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3883 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3884 // This is accomplished by using a BNEZ with the result of the SLT.
3885 //
3886 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3887 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3888 // Because only BGE and BLE branch on equality, we can use the
3889 // AcceptsEquality variable to decide when to emit the BEQZ.
3890 // Note that the order of the SLT arguments doesn't change between
3891 // opposites.
3892 //
3893 // The same applies to the unsigned variants, except that SLTu is used
3894 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003895 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3896 ReverseOrderSLT ? TrgReg : SrcReg,
3897 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003898
Daniel Sandersa736b372016-04-29 13:33:12 +00003899 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3900 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3901 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3902 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003903 return false;
3904}
3905
Simon Dardis509da1a2017-02-13 16:06:48 +00003906// Expand a integer division macro.
3907//
3908// Notably we don't have to emit a warning when encountering $rt as the $zero
3909// register, or 0 as an immediate. processInstruction() has already done that.
3910//
3911// The destination register can only be $zero when expanding (S)DivIMacro or
3912// D(S)DivMacro.
3913
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003914bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3915 const MCSubtargetInfo *STI, const bool IsMips64,
3916 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003917 MipsTargetStreamer &TOut = getTargetStreamer();
3918
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003919 warnIfNoMacro(IDLoc);
3920
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003921 const MCOperand &RdRegOp = Inst.getOperand(0);
3922 assert(RdRegOp.isReg() && "expected register operand kind");
3923 unsigned RdReg = RdRegOp.getReg();
3924
3925 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003926 assert(RsRegOp.isReg() && "expected register operand kind");
3927 unsigned RsReg = RsRegOp.getReg();
3928
Simon Dardis12850ee2017-01-31 10:49:24 +00003929 unsigned RtReg;
3930 int64_t ImmValue;
3931
3932 const MCOperand &RtOp = Inst.getOperand(2);
3933 assert((RtOp.isReg() || RtOp.isImm()) &&
3934 "expected register or immediate operand kind");
3935 if (RtOp.isReg())
3936 RtReg = RtOp.getReg();
3937 else
3938 ImmValue = RtOp.getImm();
3939
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003940 unsigned DivOp;
3941 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003942 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003943
3944 if (IsMips64) {
3945 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3946 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003947 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003948 } else {
3949 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3950 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003951 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003952 }
3953
3954 bool UseTraps = useTraps();
3955
Simon Dardis12850ee2017-01-31 10:49:24 +00003956 if (RtOp.isImm()) {
3957 unsigned ATReg = getATReg(IDLoc);
3958 if (!ATReg)
3959 return true;
3960
3961 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003962 if (UseTraps)
3963 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3964 else
3965 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3966 return false;
3967 }
3968
3969 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003970 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003971 return false;
3972 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003973 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003974 return false;
3975 } else {
3976 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3977 false, Inst.getLoc(), Out, STI))
3978 return true;
3979 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3980 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3981 return false;
3982 }
3983 return true;
3984 }
3985
Simon Dardis509da1a2017-02-13 16:06:48 +00003986 // If the macro expansion of (d)div(u) would always trap or break, insert
3987 // the trap/break and exit. This gives a different result to GAS. GAS has
3988 // an inconsistency/missed optimization in that not all cases are handled
3989 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003990 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003991 if (UseTraps) {
3992 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003993 return false;
3994 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003995 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3996 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003997 }
3998
Simon Dardis509da1a2017-02-13 16:06:48 +00003999 // Temporary label for first branch traget
4000 MCContext &Context = TOut.getStreamer().getContext();
4001 MCSymbol *BrTarget;
4002 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004003
4004 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004005 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004006 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004007 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004008 BrTarget = Context.createTempSymbol();
4009 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4010 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004011 }
4012
Daniel Sandersa736b372016-04-29 13:33:12 +00004013 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004014
4015 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004016 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004017
4018 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004019 if (!UseTraps)
4020 TOut.getStreamer().EmitLabel(BrTarget);
4021
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004022 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004023 return false;
4024 }
4025
4026 unsigned ATReg = getATReg(IDLoc);
4027 if (!ATReg)
4028 return true;
4029
Simon Dardis509da1a2017-02-13 16:06:48 +00004030 if (!UseTraps)
4031 TOut.getStreamer().EmitLabel(BrTarget);
4032
Daniel Sandersa736b372016-04-29 13:33:12 +00004033 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004034
4035 // Temporary label for the second branch target.
4036 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4037 MCOperand LabelOpEnd =
4038 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4039
4040 // Branch to the mflo instruction.
4041 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4042
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004043 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004044 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4045 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004046 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004047 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004048 }
4049
4050 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004051 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004052 else {
4053 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004054 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004055 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4056 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004057 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004058
4059 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004060 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004061 return false;
4062}
4063
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004064bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004065 SMLoc IDLoc, MCStreamer &Out,
4066 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004067 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004068
4069 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4070 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4071 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4072
4073 unsigned FirstReg = Inst.getOperand(0).getReg();
4074 unsigned SecondReg = Inst.getOperand(1).getReg();
4075 unsigned ThirdReg = Inst.getOperand(2).getReg();
4076
4077 if (hasMips1() && !hasMips2()) {
4078 unsigned ATReg = getATReg(IDLoc);
4079 if (!ATReg)
4080 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004081 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4082 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4083 TOut.emitNop(IDLoc, STI);
4084 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4085 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4086 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4087 TOut.emitNop(IDLoc, STI);
4088 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4089 : Mips::CVT_W_S,
4090 FirstReg, SecondReg, IDLoc, STI);
4091 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4092 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004093 return false;
4094 }
4095
Daniel Sandersa736b372016-04-29 13:33:12 +00004096 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4097 : Mips::TRUNC_W_S,
4098 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004099
4100 return false;
4101}
4102
Daniel Sanders6394ee52015-10-15 14:52:58 +00004103bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004104 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004105 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004106 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004107 }
4108
Toma Tabacud88d79c2015-06-23 14:39:42 +00004109 const MCOperand &DstRegOp = Inst.getOperand(0);
4110 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004111 const MCOperand &SrcRegOp = Inst.getOperand(1);
4112 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004113 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4114 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4115
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004116 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004117 unsigned DstReg = DstRegOp.getReg();
4118 unsigned SrcReg = SrcRegOp.getReg();
4119 int64_t OffsetValue = OffsetImmOp.getImm();
4120
4121 // NOTE: We always need AT for ULHU, as it is always used as the source
4122 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004123 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004124 unsigned ATReg = getATReg(IDLoc);
4125 if (!ATReg)
4126 return true;
4127
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004128 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4129 if (IsLargeOffset) {
4130 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4131 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004132 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004133 }
4134
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004135 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4136 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4137 if (isLittle())
4138 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004139
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004140 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4141 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004142
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004143 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4144 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004145
Daniel Sandersa736b372016-04-29 13:33:12 +00004146 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004147 FirstOffset, IDLoc, STI);
4148 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004149 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004150 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004151
4152 return false;
4153}
4154
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004155bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004156 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004157 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004158 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004159 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004160
4161 const MCOperand &DstRegOp = Inst.getOperand(0);
4162 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004163 const MCOperand &SrcRegOp = Inst.getOperand(1);
4164 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004165 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4166 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4167
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004168 MipsTargetStreamer &TOut = getTargetStreamer();
4169 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004170 unsigned SrcReg = SrcRegOp.getReg();
4171 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004172
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004173 warnIfNoMacro(IDLoc);
4174 unsigned ATReg = getATReg(IDLoc);
4175 if (!ATReg)
4176 return true;
4177
4178 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4179 if (IsLargeOffset) {
4180 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4181 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004182 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004183 }
4184
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004185 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4186 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4187 if (isLittle())
4188 std::swap(FirstOffset, SecondOffset);
4189
4190 if (IsLargeOffset) {
4191 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4192 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4193 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4194 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4195 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4196 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004197 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004198 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4199 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4200 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004201 }
4202
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004203 return false;
4204}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004205
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004206bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4207 const MCSubtargetInfo *STI) {
4208 if (hasMips32r6() || hasMips64r6()) {
4209 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4210 }
4211
4212 const MCOperand &DstRegOp = Inst.getOperand(0);
4213 assert(DstRegOp.isReg() && "expected register operand kind");
4214 const MCOperand &SrcRegOp = Inst.getOperand(1);
4215 assert(SrcRegOp.isReg() && "expected register operand kind");
4216 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4217 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4218
4219 MipsTargetStreamer &TOut = getTargetStreamer();
4220 unsigned DstReg = DstRegOp.getReg();
4221 unsigned SrcReg = SrcRegOp.getReg();
4222 int64_t OffsetValue = OffsetImmOp.getImm();
4223
4224 // Compute left/right load/store offsets.
4225 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4226 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4227 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4228 if (isLittle())
4229 std::swap(LxlOffset, LxrOffset);
4230
4231 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4232 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4233 unsigned TmpReg = SrcReg;
4234 if (IsLargeOffset || DoMove) {
4235 warnIfNoMacro(IDLoc);
4236 TmpReg = getATReg(IDLoc);
4237 if (!TmpReg)
4238 return true;
4239 }
4240
4241 if (IsLargeOffset) {
4242 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4243 IDLoc, Out, STI))
4244 return true;
4245 }
4246
4247 if (DoMove)
4248 std::swap(DstReg, TmpReg);
4249
4250 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4251 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4252 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4253 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4254
4255 if (DoMove)
4256 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004257
4258 return false;
4259}
4260
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004261bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004262 MCStreamer &Out,
4263 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004264 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004265
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004266 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4267 assert(Inst.getOperand(0).isReg() &&
4268 Inst.getOperand(1).isReg() &&
4269 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004270
4271 unsigned ATReg = Mips::NoRegister;
4272 unsigned FinalDstReg = Mips::NoRegister;
4273 unsigned DstReg = Inst.getOperand(0).getReg();
4274 unsigned SrcReg = Inst.getOperand(1).getReg();
4275 int64_t ImmValue = Inst.getOperand(2).getImm();
4276
Simon Dardisaa208812017-02-24 14:34:32 +00004277 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004278
4279 unsigned FinalOpcode = Inst.getOpcode();
4280
4281 if (DstReg == SrcReg) {
4282 ATReg = getATReg(Inst.getLoc());
4283 if (!ATReg)
4284 return true;
4285 FinalDstReg = DstReg;
4286 DstReg = ATReg;
4287 }
4288
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004289 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004290 switch (FinalOpcode) {
4291 default:
4292 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004293 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004294 FinalOpcode = Mips::ADD;
4295 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004296 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004297 FinalOpcode = Mips::ADDu;
4298 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004299 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004300 FinalOpcode = Mips::AND;
4301 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004302 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004303 FinalOpcode = Mips::NOR;
4304 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004305 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004306 FinalOpcode = Mips::OR;
4307 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004308 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004309 FinalOpcode = Mips::SLT;
4310 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004311 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004312 FinalOpcode = Mips::SLTu;
4313 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004314 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004315 FinalOpcode = Mips::XOR;
4316 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004317 case Mips::ADDi_MM:
4318 FinalOpcode = Mips::ADD_MM;
4319 break;
4320 case Mips::ADDiu_MM:
4321 FinalOpcode = Mips::ADDu_MM;
4322 break;
4323 case Mips::ANDi_MM:
4324 FinalOpcode = Mips::AND_MM;
4325 break;
4326 case Mips::ORi_MM:
4327 FinalOpcode = Mips::OR_MM;
4328 break;
4329 case Mips::SLTi_MM:
4330 FinalOpcode = Mips::SLT_MM;
4331 break;
4332 case Mips::SLTiu_MM:
4333 FinalOpcode = Mips::SLTu_MM;
4334 break;
4335 case Mips::XORi_MM:
4336 FinalOpcode = Mips::XOR_MM;
4337 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004338 case Mips::ANDi64:
4339 FinalOpcode = Mips::AND64;
4340 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004341 case Mips::NORImm64:
4342 FinalOpcode = Mips::NOR64;
4343 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004344 case Mips::ORi64:
4345 FinalOpcode = Mips::OR64;
4346 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004347 case Mips::SLTImm64:
4348 FinalOpcode = Mips::SLT64;
4349 break;
4350 case Mips::SLTUImm64:
4351 FinalOpcode = Mips::SLTu64;
4352 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004353 case Mips::XORi64:
4354 FinalOpcode = Mips::XOR64;
4355 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004356 }
4357
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004358 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004359 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004360 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004361 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004362 return false;
4363 }
4364 return true;
4365}
4366
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004367bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4368 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004369 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004370 unsigned ATReg = Mips::NoRegister;
4371 unsigned DReg = Inst.getOperand(0).getReg();
4372 unsigned SReg = Inst.getOperand(1).getReg();
4373 unsigned TReg = Inst.getOperand(2).getReg();
4374 unsigned TmpReg = DReg;
4375
4376 unsigned FirstShift = Mips::NOP;
4377 unsigned SecondShift = Mips::NOP;
4378
4379 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004380 if (DReg == SReg) {
4381 TmpReg = getATReg(Inst.getLoc());
4382 if (!TmpReg)
4383 return true;
4384 }
4385
4386 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004387 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4388 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004389 return false;
4390 }
4391
4392 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004393 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004394 return false;
4395 }
4396
4397 return true;
4398 }
4399
4400 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004401 switch (Inst.getOpcode()) {
4402 default:
4403 llvm_unreachable("unexpected instruction opcode");
4404 case Mips::ROL:
4405 FirstShift = Mips::SRLV;
4406 SecondShift = Mips::SLLV;
4407 break;
4408 case Mips::ROR:
4409 FirstShift = Mips::SLLV;
4410 SecondShift = Mips::SRLV;
4411 break;
4412 }
4413
4414 ATReg = getATReg(Inst.getLoc());
4415 if (!ATReg)
4416 return true;
4417
Daniel Sandersa736b372016-04-29 13:33:12 +00004418 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4419 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4420 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4421 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004422
4423 return false;
4424 }
4425
4426 return true;
4427}
4428
4429bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004430 MCStreamer &Out,
4431 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004432 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004433 unsigned ATReg = Mips::NoRegister;
4434 unsigned DReg = Inst.getOperand(0).getReg();
4435 unsigned SReg = Inst.getOperand(1).getReg();
4436 int64_t ImmValue = Inst.getOperand(2).getImm();
4437
4438 unsigned FirstShift = Mips::NOP;
4439 unsigned SecondShift = Mips::NOP;
4440
4441 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004442 if (Inst.getOpcode() == Mips::ROLImm) {
4443 uint64_t MaxShift = 32;
4444 uint64_t ShiftValue = ImmValue;
4445 if (ImmValue != 0)
4446 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004447 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004448 return false;
4449 }
4450
4451 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004452 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004453 return false;
4454 }
4455
4456 return true;
4457 }
4458
4459 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004460 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004461 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004462 return false;
4463 }
4464
4465 switch (Inst.getOpcode()) {
4466 default:
4467 llvm_unreachable("unexpected instruction opcode");
4468 case Mips::ROLImm:
4469 FirstShift = Mips::SLL;
4470 SecondShift = Mips::SRL;
4471 break;
4472 case Mips::RORImm:
4473 FirstShift = Mips::SRL;
4474 SecondShift = Mips::SLL;
4475 break;
4476 }
4477
4478 ATReg = getATReg(Inst.getLoc());
4479 if (!ATReg)
4480 return true;
4481
Daniel Sandersa736b372016-04-29 13:33:12 +00004482 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4483 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4484 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004485
4486 return false;
4487 }
4488
4489 return true;
4490}
4491
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004492bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4493 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004494 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004495 unsigned ATReg = Mips::NoRegister;
4496 unsigned DReg = Inst.getOperand(0).getReg();
4497 unsigned SReg = Inst.getOperand(1).getReg();
4498 unsigned TReg = Inst.getOperand(2).getReg();
4499 unsigned TmpReg = DReg;
4500
4501 unsigned FirstShift = Mips::NOP;
4502 unsigned SecondShift = Mips::NOP;
4503
4504 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004505 if (TmpReg == SReg) {
4506 TmpReg = getATReg(Inst.getLoc());
4507 if (!TmpReg)
4508 return true;
4509 }
4510
4511 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004512 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4513 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004514 return false;
4515 }
4516
4517 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004518 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004519 return false;
4520 }
4521
4522 return true;
4523 }
4524
4525 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004526 switch (Inst.getOpcode()) {
4527 default:
4528 llvm_unreachable("unexpected instruction opcode");
4529 case Mips::DROL:
4530 FirstShift = Mips::DSRLV;
4531 SecondShift = Mips::DSLLV;
4532 break;
4533 case Mips::DROR:
4534 FirstShift = Mips::DSLLV;
4535 SecondShift = Mips::DSRLV;
4536 break;
4537 }
4538
4539 ATReg = getATReg(Inst.getLoc());
4540 if (!ATReg)
4541 return true;
4542
Daniel Sandersa736b372016-04-29 13:33:12 +00004543 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4544 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4545 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4546 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004547
4548 return false;
4549 }
4550
4551 return true;
4552}
4553
4554bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004555 MCStreamer &Out,
4556 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004557 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004558 unsigned ATReg = Mips::NoRegister;
4559 unsigned DReg = Inst.getOperand(0).getReg();
4560 unsigned SReg = Inst.getOperand(1).getReg();
4561 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4562
4563 unsigned FirstShift = Mips::NOP;
4564 unsigned SecondShift = Mips::NOP;
4565
4566 MCInst TmpInst;
4567
4568 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004569 unsigned FinalOpcode = Mips::NOP;
4570 if (ImmValue == 0)
4571 FinalOpcode = Mips::DROTR;
4572 else if (ImmValue % 32 == 0)
4573 FinalOpcode = Mips::DROTR32;
4574 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4575 if (Inst.getOpcode() == Mips::DROLImm)
4576 FinalOpcode = Mips::DROTR32;
4577 else
4578 FinalOpcode = Mips::DROTR;
4579 } else if (ImmValue >= 33) {
4580 if (Inst.getOpcode() == Mips::DROLImm)
4581 FinalOpcode = Mips::DROTR;
4582 else
4583 FinalOpcode = Mips::DROTR32;
4584 }
4585
4586 uint64_t ShiftValue = ImmValue % 32;
4587 if (Inst.getOpcode() == Mips::DROLImm)
4588 ShiftValue = (32 - ImmValue % 32) % 32;
4589
Daniel Sandersa736b372016-04-29 13:33:12 +00004590 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004591
4592 return false;
4593 }
4594
4595 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004596 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004597 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004598 return false;
4599 }
4600
4601 switch (Inst.getOpcode()) {
4602 default:
4603 llvm_unreachable("unexpected instruction opcode");
4604 case Mips::DROLImm:
4605 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4606 FirstShift = Mips::DSLL;
4607 SecondShift = Mips::DSRL32;
4608 }
4609 if (ImmValue == 32) {
4610 FirstShift = Mips::DSLL32;
4611 SecondShift = Mips::DSRL32;
4612 }
4613 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4614 FirstShift = Mips::DSLL32;
4615 SecondShift = Mips::DSRL;
4616 }
4617 break;
4618 case Mips::DRORImm:
4619 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4620 FirstShift = Mips::DSRL;
4621 SecondShift = Mips::DSLL32;
4622 }
4623 if (ImmValue == 32) {
4624 FirstShift = Mips::DSRL32;
4625 SecondShift = Mips::DSLL32;
4626 }
4627 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4628 FirstShift = Mips::DSRL32;
4629 SecondShift = Mips::DSLL;
4630 }
4631 break;
4632 }
4633
4634 ATReg = getATReg(Inst.getLoc());
4635 if (!ATReg)
4636 return true;
4637
Daniel Sandersa736b372016-04-29 13:33:12 +00004638 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4639 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4640 Inst.getLoc(), STI);
4641 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004642
4643 return false;
4644 }
4645
4646 return true;
4647}
4648
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004649bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4650 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004651 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004652 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4653 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4654
Daniel Sandersa736b372016-04-29 13:33:12 +00004655 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004656 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004657 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004658 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004659 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4660 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004661
4662 return false;
4663}
4664
Simon Dardis3c82a642017-02-08 16:25:05 +00004665bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4666 const MCSubtargetInfo *STI) {
4667 MipsTargetStreamer &TOut = getTargetStreamer();
4668 unsigned ATReg = Mips::NoRegister;
4669 unsigned DstReg = Inst.getOperand(0).getReg();
4670 unsigned SrcReg = Inst.getOperand(1).getReg();
4671 int32_t ImmValue = Inst.getOperand(2).getImm();
4672
4673 ATReg = getATReg(IDLoc);
4674 if (!ATReg)
4675 return true;
4676
4677 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4678
4679 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4680 SrcReg, ATReg, IDLoc, STI);
4681
4682 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4683
4684 return false;
4685}
4686
4687bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4688 const MCSubtargetInfo *STI) {
4689 MipsTargetStreamer &TOut = getTargetStreamer();
4690 unsigned ATReg = Mips::NoRegister;
4691 unsigned DstReg = Inst.getOperand(0).getReg();
4692 unsigned SrcReg = Inst.getOperand(1).getReg();
4693 unsigned TmpReg = Inst.getOperand(2).getReg();
4694
4695 ATReg = getATReg(Inst.getLoc());
4696 if (!ATReg)
4697 return true;
4698
4699 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4700 SrcReg, TmpReg, IDLoc, STI);
4701
4702 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4703
4704 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4705 DstReg, DstReg, 0x1F, IDLoc, STI);
4706
4707 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4708
4709 if (useTraps()) {
4710 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4711 } else {
4712 MCContext & Context = TOut.getStreamer().getContext();
4713 MCSymbol * BrTarget = Context.createTempSymbol();
4714 MCOperand LabelOp =
4715 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4716
4717 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4718 if (AssemblerOptions.back()->isReorder())
4719 TOut.emitNop(IDLoc, STI);
4720 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4721
4722 TOut.getStreamer().EmitLabel(BrTarget);
4723 }
4724 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4725
4726 return false;
4727}
4728
4729bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4730 const MCSubtargetInfo *STI) {
4731 MipsTargetStreamer &TOut = getTargetStreamer();
4732 unsigned ATReg = Mips::NoRegister;
4733 unsigned DstReg = Inst.getOperand(0).getReg();
4734 unsigned SrcReg = Inst.getOperand(1).getReg();
4735 unsigned TmpReg = Inst.getOperand(2).getReg();
4736
4737 ATReg = getATReg(IDLoc);
4738 if (!ATReg)
4739 return true;
4740
4741 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4742 SrcReg, TmpReg, IDLoc, STI);
4743
4744 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4745 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4746 if (useTraps()) {
4747 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4748 } else {
4749 MCContext & Context = TOut.getStreamer().getContext();
4750 MCSymbol * BrTarget = Context.createTempSymbol();
4751 MCOperand LabelOp =
4752 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4753
4754 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4755 if (AssemblerOptions.back()->isReorder())
4756 TOut.emitNop(IDLoc, STI);
4757 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4758
4759 TOut.getStreamer().EmitLabel(BrTarget);
4760 }
4761
4762 return false;
4763}
4764
4765bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4766 const MCSubtargetInfo *STI) {
4767 MipsTargetStreamer &TOut = getTargetStreamer();
4768 unsigned DstReg = Inst.getOperand(0).getReg();
4769 unsigned SrcReg = Inst.getOperand(1).getReg();
4770 unsigned TmpReg = Inst.getOperand(2).getReg();
4771
4772 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4773 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4774
4775 return false;
4776}
4777
Simon Dardisaff4d142016-10-18 14:28:00 +00004778// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4779// lw $<reg+1>>, offset+4($reg2)'
4780// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4781// sw $<reg+1>>, offset+4($reg2)'
4782// for O32.
4783bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4784 MCStreamer &Out,
4785 const MCSubtargetInfo *STI,
4786 bool IsLoad) {
4787 if (!isABI_O32())
4788 return true;
4789
4790 warnIfNoMacro(IDLoc);
4791
4792 MipsTargetStreamer &TOut = getTargetStreamer();
4793 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4794 unsigned FirstReg = Inst.getOperand(0).getReg();
4795 unsigned SecondReg = nextReg(FirstReg);
4796 unsigned BaseReg = Inst.getOperand(1).getReg();
4797 if (!SecondReg)
4798 return true;
4799
4800 warnIfRegIndexIsAT(FirstReg, IDLoc);
4801
4802 assert(Inst.getOperand(2).isImm() &&
4803 "Offset for load macro is not immediate!");
4804
4805 MCOperand &FirstOffset = Inst.getOperand(2);
4806 signed NextOffset = FirstOffset.getImm() + 4;
4807 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4808
4809 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4810 return true;
4811
4812 // For loads, clobber the base register with the second load instead of the
4813 // first if the BaseReg == FirstReg.
4814 if (FirstReg != BaseReg || !IsLoad) {
4815 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4816 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4817 } else {
4818 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4819 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4820 }
4821
4822 return false;
4823}
4824
Simon Dardis43115a12016-11-21 20:30:41 +00004825bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4826 const MCSubtargetInfo *STI) {
4827
4828 warnIfNoMacro(IDLoc);
4829 MipsTargetStreamer &TOut = getTargetStreamer();
4830
4831 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4832 Inst.getOperand(2).getReg() != Mips::ZERO) {
4833 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4834 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4835 IDLoc, STI);
4836 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4837 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4838 return false;
4839 }
4840
4841 unsigned Reg = 0;
4842 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4843 Reg = Inst.getOperand(2).getReg();
4844 } else {
4845 Reg = Inst.getOperand(1).getReg();
4846 }
4847 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4848 return false;
4849}
4850
4851bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4852 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004853 warnIfNoMacro(IDLoc);
4854 MipsTargetStreamer &TOut = getTargetStreamer();
4855
4856 unsigned Opc;
4857 int64_t Imm = Inst.getOperand(2).getImm();
4858 unsigned Reg = Inst.getOperand(1).getReg();
4859
4860 if (Imm == 0) {
4861 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4862 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4863 return false;
4864 } else {
4865
4866 if (Reg == Mips::ZERO) {
4867 Warning(IDLoc, "comparison is always false");
4868 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4869 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4870 return false;
4871 }
4872
4873 if (Imm > -0x8000 && Imm < 0) {
4874 Imm = -Imm;
4875 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4876 } else {
4877 Opc = Mips::XORi;
4878 }
4879 }
4880 if (!isUInt<16>(Imm)) {
4881 unsigned ATReg = getATReg(IDLoc);
4882 if (!ATReg)
4883 return true;
4884
4885 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4886 Out, STI))
4887 return true;
4888
4889 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4890 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4891 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4892 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4893 return false;
4894 }
4895
4896 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4897 Imm, IDLoc, STI);
4898 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4899 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4900 return false;
4901}
4902
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004903// Map the DSP accumulator and control register to the corresponding gpr
4904// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4905// do not map the DSP registers contigously to gpr registers.
4906static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4907 switch (Inst.getOpcode()) {
4908 case Mips::MFTLO:
4909 case Mips::MTTLO:
4910 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4911 case Mips::AC0:
4912 return Mips::ZERO;
4913 case Mips::AC1:
4914 return Mips::A0;
4915 case Mips::AC2:
4916 return Mips::T0;
4917 case Mips::AC3:
4918 return Mips::T4;
4919 default:
4920 llvm_unreachable("Unknown register for 'mttr' alias!");
4921 }
4922 case Mips::MFTHI:
4923 case Mips::MTTHI:
4924 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4925 case Mips::AC0:
4926 return Mips::AT;
4927 case Mips::AC1:
4928 return Mips::A1;
4929 case Mips::AC2:
4930 return Mips::T1;
4931 case Mips::AC3:
4932 return Mips::T5;
4933 default:
4934 llvm_unreachable("Unknown register for 'mttr' alias!");
4935 }
4936 case Mips::MFTACX:
4937 case Mips::MTTACX:
4938 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4939 case Mips::AC0:
4940 return Mips::V0;
4941 case Mips::AC1:
4942 return Mips::A2;
4943 case Mips::AC2:
4944 return Mips::T2;
4945 case Mips::AC3:
4946 return Mips::T6;
4947 default:
4948 llvm_unreachable("Unknown register for 'mttr' alias!");
4949 }
4950 case Mips::MFTDSP:
4951 case Mips::MTTDSP:
4952 return Mips::S0;
4953 default:
4954 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4955 }
4956}
4957
4958// Map the floating point register operand to the corresponding register
4959// operand.
4960static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4961 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4962 case Mips::F0: return Mips::ZERO;
4963 case Mips::F1: return Mips::AT;
4964 case Mips::F2: return Mips::V0;
4965 case Mips::F3: return Mips::V1;
4966 case Mips::F4: return Mips::A0;
4967 case Mips::F5: return Mips::A1;
4968 case Mips::F6: return Mips::A2;
4969 case Mips::F7: return Mips::A3;
4970 case Mips::F8: return Mips::T0;
4971 case Mips::F9: return Mips::T1;
4972 case Mips::F10: return Mips::T2;
4973 case Mips::F11: return Mips::T3;
4974 case Mips::F12: return Mips::T4;
4975 case Mips::F13: return Mips::T5;
4976 case Mips::F14: return Mips::T6;
4977 case Mips::F15: return Mips::T7;
4978 case Mips::F16: return Mips::S0;
4979 case Mips::F17: return Mips::S1;
4980 case Mips::F18: return Mips::S2;
4981 case Mips::F19: return Mips::S3;
4982 case Mips::F20: return Mips::S4;
4983 case Mips::F21: return Mips::S5;
4984 case Mips::F22: return Mips::S6;
4985 case Mips::F23: return Mips::S7;
4986 case Mips::F24: return Mips::T8;
4987 case Mips::F25: return Mips::T9;
4988 case Mips::F26: return Mips::K0;
4989 case Mips::F27: return Mips::K1;
4990 case Mips::F28: return Mips::GP;
4991 case Mips::F29: return Mips::SP;
4992 case Mips::F30: return Mips::FP;
4993 case Mips::F31: return Mips::RA;
4994 default: llvm_unreachable("Unknown register for mttc1 alias!");
4995 }
4996}
4997
4998// Map the coprocessor operand the corresponding gpr register operand.
4999static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5000 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5001 case Mips::COP00: return Mips::ZERO;
5002 case Mips::COP01: return Mips::AT;
5003 case Mips::COP02: return Mips::V0;
5004 case Mips::COP03: return Mips::V1;
5005 case Mips::COP04: return Mips::A0;
5006 case Mips::COP05: return Mips::A1;
5007 case Mips::COP06: return Mips::A2;
5008 case Mips::COP07: return Mips::A3;
5009 case Mips::COP08: return Mips::T0;
5010 case Mips::COP09: return Mips::T1;
5011 case Mips::COP010: return Mips::T2;
5012 case Mips::COP011: return Mips::T3;
5013 case Mips::COP012: return Mips::T4;
5014 case Mips::COP013: return Mips::T5;
5015 case Mips::COP014: return Mips::T6;
5016 case Mips::COP015: return Mips::T7;
5017 case Mips::COP016: return Mips::S0;
5018 case Mips::COP017: return Mips::S1;
5019 case Mips::COP018: return Mips::S2;
5020 case Mips::COP019: return Mips::S3;
5021 case Mips::COP020: return Mips::S4;
5022 case Mips::COP021: return Mips::S5;
5023 case Mips::COP022: return Mips::S6;
5024 case Mips::COP023: return Mips::S7;
5025 case Mips::COP024: return Mips::T8;
5026 case Mips::COP025: return Mips::T9;
5027 case Mips::COP026: return Mips::K0;
5028 case Mips::COP027: return Mips::K1;
5029 case Mips::COP028: return Mips::GP;
5030 case Mips::COP029: return Mips::SP;
5031 case Mips::COP030: return Mips::FP;
5032 case Mips::COP031: return Mips::RA;
5033 default: llvm_unreachable("Unknown register for mttc0 alias!");
5034 }
5035}
5036
5037/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5038/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5039bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5040 const MCSubtargetInfo *STI) {
5041 MipsTargetStreamer &TOut = getTargetStreamer();
5042 unsigned rd = 0;
5043 unsigned u = 1;
5044 unsigned sel = 0;
5045 unsigned h = 0;
5046 bool IsMFTR = false;
5047 switch (Inst.getOpcode()) {
5048 case Mips::MFTC0:
5049 IsMFTR = true;
5050 LLVM_FALLTHROUGH;
5051 case Mips::MTTC0:
5052 u = 0;
5053 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5054 sel = Inst.getOperand(2).getImm();
5055 break;
5056 case Mips::MFTGPR:
5057 IsMFTR = true;
5058 LLVM_FALLTHROUGH;
5059 case Mips::MTTGPR:
5060 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5061 break;
5062 case Mips::MFTLO:
5063 case Mips::MFTHI:
5064 case Mips::MFTACX:
5065 case Mips::MFTDSP:
5066 IsMFTR = true;
5067 LLVM_FALLTHROUGH;
5068 case Mips::MTTLO:
5069 case Mips::MTTHI:
5070 case Mips::MTTACX:
5071 case Mips::MTTDSP:
5072 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5073 sel = 1;
5074 break;
5075 case Mips::MFTHC1:
5076 h = 1;
5077 LLVM_FALLTHROUGH;
5078 case Mips::MFTC1:
5079 IsMFTR = true;
5080 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5081 sel = 2;
5082 break;
5083 case Mips::MTTHC1:
5084 h = 1;
5085 LLVM_FALLTHROUGH;
5086 case Mips::MTTC1:
5087 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5088 sel = 2;
5089 break;
5090 case Mips::CFTC1:
5091 IsMFTR = true;
5092 LLVM_FALLTHROUGH;
5093 case Mips::CTTC1:
5094 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5095 sel = 3;
5096 break;
5097 }
5098 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5099 unsigned Op1 =
5100 IsMFTR ? rd
5101 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5102 : Inst.getOperand(0).getReg());
5103
5104 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5105 STI);
5106 return false;
5107}
5108
Daniel Sandersc5537422016-07-27 13:49:44 +00005109unsigned
5110MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5111 const OperandVector &Operands) {
5112 switch (Inst.getOpcode()) {
5113 default:
5114 return Match_Success;
5115 case Mips::DATI:
5116 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005117 case Mips::DATI_MM64R6:
5118 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005119 if (static_cast<MipsOperand &>(*Operands[1])
5120 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5121 return Match_Success;
5122 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005123 }
5124}
Simon Dardis730fdb72017-01-16 13:55:58 +00005125
Matheus Almeida595fcab2014-06-11 15:05:56 +00005126unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005127 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005128 // As described by the MIPSR6 spec, daui must not use the zero operand for
5129 // its source operand.
5130 case Mips::DAUI:
5131 case Mips::DAUI_MM64R6:
5132 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5133 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5134 return Match_RequiresNoZeroRegister;
5135 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005136 // As described by the Mips32r2 spec, the registers Rd and Rs for
5137 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005138 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005139 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005140 case Mips::JALR_HB:
5141 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005142 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005143 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5144 return Match_RequiresDifferentSrcAndDst;
5145 return Match_Success;
5146 case Mips::LWP_MM:
5147 case Mips::LWP_MMR6:
5148 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5149 return Match_RequiresDifferentSrcAndDst;
5150 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005151 case Mips::SYNC:
5152 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5153 return Match_NonZeroOperandForSync;
5154 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005155 // As described the MIPSR6 spec, the compact branches that compare registers
5156 // must:
5157 // a) Not use the zero register.
5158 // b) Not use the same register twice.
5159 // c) rs < rt for bnec, beqc.
5160 // NB: For this case, the encoding will swap the operands as their
5161 // ordering doesn't matter. GAS performs this transformation too.
5162 // Hence, that constraint does not have to be enforced.
5163 //
5164 // The compact branches that branch iff the signed addition of two registers
5165 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5166 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005167 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5168 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5169 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5170 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5171 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5172 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005173 case Mips::BLEZC64:
5174 case Mips::BGEZC64:
5175 case Mips::BGTZC64:
5176 case Mips::BLTZC64:
5177 case Mips::BEQZC64:
5178 case Mips::BNEZC64:
5179 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5180 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005181 return Match_RequiresNoZeroRegister;
5182 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005183 case Mips::BGEC: case Mips::BGEC_MMR6:
5184 case Mips::BLTC: case Mips::BLTC_MMR6:
5185 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5186 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5187 case Mips::BEQC: case Mips::BEQC_MMR6:
5188 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005189 case Mips::BGEC64:
5190 case Mips::BLTC64:
5191 case Mips::BGEUC64:
5192 case Mips::BLTUC64:
5193 case Mips::BEQC64:
5194 case Mips::BNEC64:
5195 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5196 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005197 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005198 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5199 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005200 return Match_RequiresNoZeroRegister;
5201 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5202 return Match_RequiresDifferentOperands;
5203 return Match_Success;
Simon Dardis55e44672017-09-14 17:27:53 +00005204 case Mips::DINS:
5205 case Mips::DINS_MM64R6: {
5206 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5207 "Operands must be immediates for dins!");
5208 const signed Pos = Inst.getOperand(2).getImm();
5209 const signed Size = Inst.getOperand(3).getImm();
5210 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5211 return Match_RequiresPosSizeRange0_32;
5212 return Match_Success;
5213 }
5214 case Mips::DINSM:
5215 case Mips::DINSM_MM64R6:
5216 case Mips::DINSU:
5217 case Mips::DINSU_MM64R6: {
5218 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5219 "Operands must be immediates for dinsm/dinsu!");
5220 const signed Pos = Inst.getOperand(2).getImm();
5221 const signed Size = Inst.getOperand(3).getImm();
5222 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5223 return Match_RequiresPosSizeRange33_64;
5224 return Match_Success;
5225 }
5226 case Mips::DEXT:
5227 case Mips::DEXT_MM64R6: {
5228 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5229 "Operands must be immediates for DEXTM!");
5230 const signed Pos = Inst.getOperand(2).getImm();
5231 const signed Size = Inst.getOperand(3).getImm();
5232 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5233 return Match_RequiresPosSizeUImm6;
5234 return Match_Success;
5235 }
5236 case Mips::DEXTM:
5237 case Mips::DEXTU:
5238 case Mips::DEXTM_MM64R6:
5239 case Mips::DEXTU_MM64R6: {
5240 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5241 "Operands must be immediates for dextm/dextu!");
5242 const signed Pos = Inst.getOperand(2).getImm();
5243 const signed Size = Inst.getOperand(3).getImm();
5244 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5245 return Match_RequiresPosSizeRange33_64;
5246 return Match_Success;
5247 }
Simon Dardisb60833c2016-05-31 17:34:42 +00005248 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005249
5250 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5251 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5252 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5253 return Match_NoFCCRegisterForCurrentISA;
5254
5255 return Match_Success;
5256
Matheus Almeida595fcab2014-06-11 15:05:56 +00005257}
5258
Daniel Sanders52da7af2015-11-06 12:11:03 +00005259static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5260 uint64_t ErrorInfo) {
5261 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5262 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5263 if (ErrorLoc == SMLoc())
5264 return Loc;
5265 return ErrorLoc;
5266 }
5267 return Loc;
5268}
5269
David Blaikie960ea3f2014-06-08 16:18:35 +00005270bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5271 OperandVector &Operands,
5272 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005273 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005274 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005275 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005276 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005277 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005278
5279 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005280 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005281 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005282 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005283 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005284 case Match_MissingFeature:
5285 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5286 return true;
5287 case Match_InvalidOperand: {
5288 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005289 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005290 if (ErrorInfo >= Operands.size())
5291 return Error(IDLoc, "too few operands for instruction");
5292
Daniel Sanders52da7af2015-11-06 12:11:03 +00005293 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005294 if (ErrorLoc == SMLoc())
5295 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005296 }
5297
5298 return Error(ErrorLoc, "invalid operand for instruction");
5299 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005300 case Match_NonZeroOperandForSync:
5301 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005302 case Match_MnemonicFail:
5303 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005304 case Match_RequiresDifferentSrcAndDst:
5305 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005306 case Match_RequiresDifferentOperands:
5307 return Error(IDLoc, "registers must be different");
5308 case Match_RequiresNoZeroRegister:
5309 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005310 case Match_RequiresSameSrcAndDst:
5311 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005312 case Match_NoFCCRegisterForCurrentISA:
5313 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5314 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005315 case Match_Immz:
5316 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005317 case Match_UImm1_0:
5318 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5319 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005320 case Match_UImm2_0:
5321 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5322 "expected 2-bit unsigned immediate");
5323 case Match_UImm2_1:
5324 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5325 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005326 case Match_UImm3_0:
5327 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5328 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005329 case Match_UImm4_0:
5330 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5331 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005332 case Match_SImm4_0:
5333 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5334 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005335 case Match_UImm5_0:
5336 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5337 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005338 case Match_SImm5_0:
5339 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5340 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005341 case Match_UImm5_1:
5342 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5343 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005344 case Match_UImm5_32:
5345 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5346 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005347 case Match_UImm5_33:
5348 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5349 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005350 case Match_UImm5_0_Report_UImm6:
5351 // This is used on UImm5 operands that have a corresponding UImm5_32
5352 // operand to avoid confusing the user.
5353 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5354 "expected 6-bit unsigned immediate");
5355 case Match_UImm5_Lsl2:
5356 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5357 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005358 case Match_UImmRange2_64:
5359 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5360 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005361 case Match_UImm6_0:
5362 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5363 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005364 case Match_UImm6_Lsl2:
5365 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5366 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005367 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005368 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5369 "expected 6-bit signed immediate");
5370 case Match_UImm7_0:
5371 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5372 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005373 case Match_UImm7_N1:
5374 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5375 "expected immediate in range -1 .. 126");
5376 case Match_SImm7_Lsl2:
5377 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5378 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005379 case Match_UImm8_0:
5380 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5381 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005382 case Match_UImm10_0:
5383 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5384 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005385 case Match_SImm10_0:
5386 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5387 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005388 case Match_SImm11_0:
5389 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5390 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005391 case Match_UImm16:
5392 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005393 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005394 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5395 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005396 case Match_SImm16:
5397 case Match_SImm16_Relaxed:
5398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5399 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005400 case Match_SImm19_Lsl2:
5401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5402 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005403 case Match_UImm20_0:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005406 case Match_UImm26_0:
5407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5408 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005409 case Match_SImm32:
5410 case Match_SImm32_Relaxed:
5411 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5412 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005413 case Match_UImm32_Coerced:
5414 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5415 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005416 case Match_MemSImm9:
5417 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5418 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005419 case Match_MemSImm10:
5420 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5421 "expected memory with 10-bit signed offset");
5422 case Match_MemSImm10Lsl1:
5423 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5424 "expected memory with 11-bit signed offset and multiple of 2");
5425 case Match_MemSImm10Lsl2:
5426 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5427 "expected memory with 12-bit signed offset and multiple of 4");
5428 case Match_MemSImm10Lsl3:
5429 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5430 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005431 case Match_MemSImm11:
5432 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5433 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005434 case Match_MemSImm12:
5435 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5436 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005437 case Match_MemSImm16:
5438 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5439 "expected memory with 16-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005440 case Match_RequiresPosSizeRange0_32: {
5441 SMLoc ErrorStart = Operands[3]->getStartLoc();
5442 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5443 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5444 SMRange(ErrorStart, ErrorEnd));
5445 }
Simon Dardis55e44672017-09-14 17:27:53 +00005446 case Match_RequiresPosSizeUImm6: {
5447 SMLoc ErrorStart = Operands[3]->getStartLoc();
5448 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5449 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5450 SMRange(ErrorStart, ErrorEnd));
5451 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005452 case Match_RequiresPosSizeRange33_64: {
5453 SMLoc ErrorStart = Operands[3]->getStartLoc();
5454 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5455 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5456 SMRange(ErrorStart, ErrorEnd));
5457 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005458 }
Craig Topper589ceee2015-01-03 08:16:34 +00005459
5460 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005461}
5462
Toma Tabacud9d344b2015-04-27 14:05:04 +00005463void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5464 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5465 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5466 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005467}
5468
Toma Tabacu81496c12015-05-20 08:54:45 +00005469void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5470 if (!AssemblerOptions.back()->isMacro())
5471 Warning(Loc, "macro instruction expanded into multiple instructions");
5472}
5473
Daniel Sandersef638fe2014-10-03 15:37:37 +00005474void
5475MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5476 SMRange Range, bool ShowColors) {
5477 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005478 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005479 ShowColors);
5480}
5481
Jack Carter1ac53222013-02-20 23:11:17 +00005482int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005483 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005484
Vladimir Medic4c299852013-11-06 11:27:05 +00005485 CC = StringSwitch<unsigned>(Name)
5486 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005487 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005488 .Case("a0", 4)
5489 .Case("a1", 5)
5490 .Case("a2", 6)
5491 .Case("a3", 7)
5492 .Case("v0", 2)
5493 .Case("v1", 3)
5494 .Case("s0", 16)
5495 .Case("s1", 17)
5496 .Case("s2", 18)
5497 .Case("s3", 19)
5498 .Case("s4", 20)
5499 .Case("s5", 21)
5500 .Case("s6", 22)
5501 .Case("s7", 23)
5502 .Case("k0", 26)
5503 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005504 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005505 .Case("sp", 29)
5506 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005507 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005508 .Case("ra", 31)
5509 .Case("t0", 8)
5510 .Case("t1", 9)
5511 .Case("t2", 10)
5512 .Case("t3", 11)
5513 .Case("t4", 12)
5514 .Case("t5", 13)
5515 .Case("t6", 14)
5516 .Case("t7", 15)
5517 .Case("t8", 24)
5518 .Case("t9", 25)
5519 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005520
Toma Tabacufda445c2014-09-15 15:33:01 +00005521 if (!(isABI_N32() || isABI_N64()))
5522 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005523
Daniel Sandersef638fe2014-10-03 15:37:37 +00005524 if (12 <= CC && CC <= 15) {
5525 // Name is one of t4-t7
5526 AsmToken RegTok = getLexer().peekTok();
5527 SMRange RegRange = RegTok.getLocRange();
5528
5529 StringRef FixedName = StringSwitch<StringRef>(Name)
5530 .Case("t4", "t0")
5531 .Case("t5", "t1")
5532 .Case("t6", "t2")
5533 .Case("t7", "t3")
5534 .Default("");
5535 assert(FixedName != "" && "Register name is not one of t4-t7.");
5536
5537 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5538 "Did you mean $" + FixedName + "?", RegRange);
5539 }
5540
Toma Tabacufda445c2014-09-15 15:33:01 +00005541 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5542 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5543 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5544 if (8 <= CC && CC <= 11)
5545 CC += 4;
5546
5547 if (CC == -1)
5548 CC = StringSwitch<unsigned>(Name)
5549 .Case("a4", 8)
5550 .Case("a5", 9)
5551 .Case("a6", 10)
5552 .Case("a7", 11)
5553 .Case("kt0", 26)
5554 .Case("kt1", 27)
5555 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005556
5557 return CC;
5558}
Jack Carterd0bd6422013-04-18 00:41:53 +00005559
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005560int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5561 int CC;
5562
5563 CC = StringSwitch<unsigned>(Name)
5564 .Case("hwr_cpunum", 0)
5565 .Case("hwr_synci_step", 1)
5566 .Case("hwr_cc", 2)
5567 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005568 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005569 .Default(-1);
5570
5571 return CC;
5572}
5573
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005574int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005575 if (Name[0] == 'f') {
5576 StringRef NumString = Name.substr(1);
5577 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005578 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005579 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005580 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005581 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005582 return IntVal;
5583 }
5584 return -1;
5585}
Jack Cartera63b16a2012-09-07 00:23:42 +00005586
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005587int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005588 if (Name.startswith("fcc")) {
5589 StringRef NumString = Name.substr(3);
5590 unsigned IntVal;
5591 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005592 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005593 if (IntVal > 7) // There are only 8 fcc registers.
5594 return -1;
5595 return IntVal;
5596 }
5597 return -1;
5598}
5599
5600int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005601 if (Name.startswith("ac")) {
5602 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005603 unsigned IntVal;
5604 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005605 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005606 if (IntVal > 3) // There are only 3 acc registers.
5607 return -1;
5608 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005609 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005610 return -1;
5611}
Jack Carterd0bd6422013-04-18 00:41:53 +00005612
Jack Carter5dc8ac92013-09-25 23:50:44 +00005613int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5614 unsigned IntVal;
5615
5616 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5617 return -1;
5618
5619 if (IntVal > 31)
5620 return -1;
5621
5622 return IntVal;
5623}
5624
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005625int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5626 int CC;
5627
5628 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005629 .Case("msair", 0)
5630 .Case("msacsr", 1)
5631 .Case("msaaccess", 2)
5632 .Case("msasave", 3)
5633 .Case("msamodify", 4)
5634 .Case("msarequest", 5)
5635 .Case("msamap", 6)
5636 .Case("msaunmap", 7)
5637 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005638
5639 return CC;
5640}
5641
Simon Dardis3aa8a902017-02-06 12:43:46 +00005642bool MipsAsmParser::canUseATReg() {
5643 return AssemblerOptions.back()->getATRegIndex() != 0;
5644}
5645
Toma Tabacu89a712b2015-04-15 10:48:56 +00005646unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005647 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005648 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005649 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005650 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005651 return 0;
5652 }
5653 unsigned AT = getReg(
5654 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005655 return AT;
5656}
Jack Carter0b744b32012-10-04 02:29:46 +00005657
Jack Carterd0bd6422013-04-18 00:41:53 +00005658unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005659 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005660}
5661
Toma Tabacu13964452014-09-04 13:23:44 +00005662bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005663 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005664 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005665
Jack Carter30a59822012-10-04 04:03:53 +00005666 // Check if the current operand has a custom associated parser, if so, try to
5667 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005668 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5669 if (ResTy == MatchOperand_Success)
5670 return false;
5671 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5672 // there was a match, but an error occurred, in which case, just return that
5673 // the operand parsing failed.
5674 if (ResTy == MatchOperand_ParseFail)
5675 return true;
5676
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005677 DEBUG(dbgs() << ".. Generic Parser\n");
5678
Jack Carterb4dbc172012-09-05 23:34:03 +00005679 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005680 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005681 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005682 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005683
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005684 // Almost all registers have been parsed by custom parsers. There is only
5685 // one exception to this. $zero (and it's alias $0) will reach this point
5686 // for div, divu, and similar instructions because it is not an operand
5687 // to the instruction definition but an explicit register. Special case
5688 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005689 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005690 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005691
Jack Carterd0bd6422013-04-18 00:41:53 +00005692 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005693 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005694 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005695 return true;
5696
Jack Carter873c7242013-01-12 01:03:14 +00005697 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005698 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005699 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005700 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005701 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005702
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005703 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005704 return false;
5705 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005706 default: {
5707 DEBUG(dbgs() << ".. generic integer expression\n");
5708
5709 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005710 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005711 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005712 return true;
5713
Jack Carter873c7242013-01-12 01:03:14 +00005714 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5715
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005716 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005717 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005718 }
Jack Carter0b744b32012-10-04 02:29:46 +00005719 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005720 return true;
5721}
5722
Jack Carterb5cf5902013-04-17 00:18:04 +00005723bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005724 switch (Expr->getKind()) {
5725 case MCExpr::Constant:
5726 return true;
5727 case MCExpr::SymbolRef:
5728 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005729 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005730 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005731 if (!isEvaluated(BE->getLHS()))
5732 return false;
5733 return isEvaluated(BE->getRHS());
5734 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005735 case MCExpr::Unary:
5736 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005737 case MCExpr::Target:
5738 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005739 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005740 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005741}
Jack Carterd0bd6422013-04-18 00:41:53 +00005742
Jack Carterb4dbc172012-09-05 23:34:03 +00005743bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5744 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005745 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005746 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005747 if (ResTy == MatchOperand_Success) {
5748 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005749 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005750 StartLoc = Operand.getStartLoc();
5751 EndLoc = Operand.getEndLoc();
5752
5753 // AFAIK, we only support numeric registers and named GPR's in CFI
5754 // directives.
5755 // Don't worry about eating tokens before failing. Using an unrecognised
5756 // register is a parse error.
5757 if (Operand.isGPRAsmReg()) {
5758 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005759 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005760 }
5761
5762 return (RegNo == (unsigned)-1);
5763 }
5764
5765 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005766 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005767}
5768
Jack Carterb5cf5902013-04-17 00:18:04 +00005769bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005770 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005771
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005772 if (isParenExpr)
5773 return getParser().parseParenExprOfDepth(0, Res, S);
5774 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005775}
5776
Alex Bradbury58eba092016-11-01 16:32:05 +00005777OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005778MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005779 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005780 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005781 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005782 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005783 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005784 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005785 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005786 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005787
Jack Carterb5cf5902013-04-17 00:18:04 +00005788 if (getLexer().getKind() == AsmToken::LParen) {
5789 Parser.Lex();
5790 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005791 }
5792
Jack Carterb5cf5902013-04-17 00:18:04 +00005793 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005794 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005795 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005796
Jack Carterd0bd6422013-04-18 00:41:53 +00005797 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005798 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005799 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005800 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005801 SMLoc E =
5802 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005803 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005804 return MatchOperand_Success;
5805 }
5806 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005807 SMLoc E =
5808 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005809
Jack Carterd0bd6422013-04-18 00:41:53 +00005810 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005811 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005812 auto Base = MipsOperand::createGPRReg(
5813 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005814 Operands.push_back(
5815 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005816 return MatchOperand_Success;
5817 }
Simon Dardis858915f2016-10-18 15:17:17 +00005818 MCBinaryExpr::Opcode Opcode;
5819 // GAS and LLVM treat comparison operators different. GAS will generate -1
5820 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5821 // highly unlikely to be found in a memory offset expression, we don't
5822 // handle them.
5823 switch (Tok.getKind()) {
5824 case AsmToken::Plus:
5825 Opcode = MCBinaryExpr::Add;
5826 Parser.Lex();
5827 break;
5828 case AsmToken::Minus:
5829 Opcode = MCBinaryExpr::Sub;
5830 Parser.Lex();
5831 break;
5832 case AsmToken::Star:
5833 Opcode = MCBinaryExpr::Mul;
5834 Parser.Lex();
5835 break;
5836 case AsmToken::Pipe:
5837 Opcode = MCBinaryExpr::Or;
5838 Parser.Lex();
5839 break;
5840 case AsmToken::Amp:
5841 Opcode = MCBinaryExpr::And;
5842 Parser.Lex();
5843 break;
5844 case AsmToken::LessLess:
5845 Opcode = MCBinaryExpr::Shl;
5846 Parser.Lex();
5847 break;
5848 case AsmToken::GreaterGreater:
5849 Opcode = MCBinaryExpr::LShr;
5850 Parser.Lex();
5851 break;
5852 case AsmToken::Caret:
5853 Opcode = MCBinaryExpr::Xor;
5854 Parser.Lex();
5855 break;
5856 case AsmToken::Slash:
5857 Opcode = MCBinaryExpr::Div;
5858 Parser.Lex();
5859 break;
5860 case AsmToken::Percent:
5861 Opcode = MCBinaryExpr::Mod;
5862 Parser.Lex();
5863 break;
5864 default:
5865 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5866 return MatchOperand_ParseFail;
5867 }
5868 const MCExpr * NextExpr;
5869 if (getParser().parseExpression(NextExpr))
5870 return MatchOperand_ParseFail;
5871 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005872 }
5873
Jack Carterd0bd6422013-04-18 00:41:53 +00005874 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005875 }
5876
Toma Tabacu13964452014-09-04 13:23:44 +00005877 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005878 if (Res != MatchOperand_Success)
5879 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005880
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005881 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005882 Error(Parser.getTok().getLoc(), "')' expected");
5883 return MatchOperand_ParseFail;
5884 }
5885
Jack Carter873c7242013-01-12 01:03:14 +00005886 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5887
Jack Carterd0bd6422013-04-18 00:41:53 +00005888 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005889
Craig Topper062a2ba2014-04-25 05:30:21 +00005890 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005891 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005892
Jack Carterd0bd6422013-04-18 00:41:53 +00005893 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005894 std::unique_ptr<MipsOperand> op(
5895 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005896 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005897 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005898 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005899 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005900 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5901 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005902 if (IdVal->evaluateAsAbsolute(Imm))
5903 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005904 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005905 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005906 getContext());
5907 }
5908
David Blaikie960ea3f2014-06-08 16:18:35 +00005909 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005910 return MatchOperand_Success;
5911}
5912
David Blaikie960ea3f2014-06-08 16:18:35 +00005913bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005914 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005915 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005916 if (Sym) {
5917 SMLoc S = Parser.getTok().getLoc();
5918 const MCExpr *Expr;
5919 if (Sym->isVariable())
5920 Expr = Sym->getVariableValue();
5921 else
5922 return false;
5923 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005924 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005925 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005926 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005927 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005928 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005929 if (ResTy == MatchOperand_Success) {
5930 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005931 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005932 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005933 llvm_unreachable("Should never ParseFail");
5934 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005935 }
Jack Carterd76b2372013-03-21 21:44:16 +00005936 }
5937 }
5938 return false;
5939}
Jack Carterd0bd6422013-04-18 00:41:53 +00005940
Alex Bradbury58eba092016-11-01 16:32:05 +00005941OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005942MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005943 StringRef Identifier,
5944 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005945 int Index = matchCPURegisterName(Identifier);
5946 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005947 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005948 Index, Identifier, getContext().getRegisterInfo(), S,
5949 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005950 return MatchOperand_Success;
5951 }
5952
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005953 Index = matchHWRegsRegisterName(Identifier);
5954 if (Index != -1) {
5955 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005956 Index, Identifier, getContext().getRegisterInfo(), S,
5957 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005958 return MatchOperand_Success;
5959 }
5960
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005961 Index = matchFPURegisterName(Identifier);
5962 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005963 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005964 Index, Identifier, getContext().getRegisterInfo(), S,
5965 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005966 return MatchOperand_Success;
5967 }
5968
5969 Index = matchFCCRegisterName(Identifier);
5970 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005971 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005972 Index, Identifier, getContext().getRegisterInfo(), S,
5973 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005974 return MatchOperand_Success;
5975 }
5976
5977 Index = matchACRegisterName(Identifier);
5978 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005979 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005980 Index, Identifier, getContext().getRegisterInfo(), S,
5981 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005982 return MatchOperand_Success;
5983 }
5984
5985 Index = matchMSA128RegisterName(Identifier);
5986 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005987 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005988 Index, Identifier, getContext().getRegisterInfo(), S,
5989 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005990 return MatchOperand_Success;
5991 }
5992
5993 Index = matchMSA128CtrlRegisterName(Identifier);
5994 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005995 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005996 Index, Identifier, getContext().getRegisterInfo(), S,
5997 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005998 return MatchOperand_Success;
5999 }
6000
6001 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006002}
6003
Alex Bradbury58eba092016-11-01 16:32:05 +00006004OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006005MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006006 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00006007 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006008
6009 if (Token.is(AsmToken::Identifier)) {
6010 DEBUG(dbgs() << ".. identifier\n");
6011 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006012 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006013 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006014 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006015 } else if (Token.is(AsmToken::Integer)) {
6016 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00006017 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006018 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
6019 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006020 return MatchOperand_Success;
6021 }
6022
6023 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
6024
6025 return MatchOperand_NoMatch;
6026}
6027
Alex Bradbury58eba092016-11-01 16:32:05 +00006028OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006029MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006030 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006031 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006032
6033 auto Token = Parser.getTok();
6034
6035 SMLoc S = Token.getLoc();
6036
6037 if (Token.isNot(AsmToken::Dollar)) {
6038 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
6039 if (Token.is(AsmToken::Identifier)) {
6040 if (searchSymbolAlias(Operands))
6041 return MatchOperand_Success;
6042 }
6043 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
6044 return MatchOperand_NoMatch;
6045 }
6046 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006047
Toma Tabacu13964452014-09-04 13:23:44 +00006048 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006049 if (ResTy == MatchOperand_Success) {
6050 Parser.Lex(); // $
6051 Parser.Lex(); // identifier
6052 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006053 return ResTy;
6054}
6055
Alex Bradbury58eba092016-11-01 16:32:05 +00006056OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006057MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006058 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006059 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006060
6061 SMLoc S = getLexer().getLoc();
6062
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006063 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006064 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006065 if (ResTy != MatchOperand_NoMatch)
6066 return ResTy;
6067
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006068 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006069 const MCExpr *Expr = nullptr;
6070 if (Parser.parseExpression(Expr)) {
6071 // We have no way of knowing if a symbol was consumed so we must ParseFail
6072 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006073 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006074 Operands.push_back(
6075 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006076 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006077}
6078
Alex Bradbury58eba092016-11-01 16:32:05 +00006079OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006080MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006081 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006082 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006083 // If the first token is '$' we may have register operand. We have to reject
6084 // cases where it is not a register. Complicating the matter is that
6085 // register names are not reserved across all ABIs.
6086 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006087 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006088 if (Parser.getTok().is(AsmToken::Dollar)) {
6089 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6090 ? MatchOperand_ParseFail
6091 : MatchOperand_NoMatch;
6092 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006093 if (getParser().parseExpression(IdVal))
6094 return MatchOperand_ParseFail;
6095 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006096 if (!MCE)
6097 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006098 int64_t Val = MCE->getValue();
6099 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6100 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006101 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006102 return MatchOperand_Success;
6103}
6104
Alex Bradbury58eba092016-11-01 16:32:05 +00006105OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006106MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6107 MCAsmParser &Parser = getParser();
6108 SmallVector<unsigned, 10> Regs;
6109 unsigned RegNo;
6110 unsigned PrevReg = Mips::NoRegister;
6111 bool RegRange = false;
6112 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6113
6114 if (Parser.getTok().isNot(AsmToken::Dollar))
6115 return MatchOperand_ParseFail;
6116
6117 SMLoc S = Parser.getTok().getLoc();
6118 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6119 SMLoc E = getLexer().getLoc();
6120 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6121 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6122 if (RegRange) {
6123 // Remove last register operand because registers from register range
6124 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006125 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6126 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006127 Regs.push_back(RegNo);
6128 } else {
6129 unsigned TmpReg = PrevReg + 1;
6130 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006131 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6132 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6133 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006134 Error(E, "invalid register operand");
6135 return MatchOperand_ParseFail;
6136 }
6137
6138 PrevReg = TmpReg;
6139 Regs.push_back(TmpReg++);
6140 }
6141 }
6142
6143 RegRange = false;
6144 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006145 if ((PrevReg == Mips::NoRegister) &&
6146 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6147 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006148 Error(E, "$16 or $31 expected");
6149 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006150 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6151 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6152 !isGP64bit()) ||
6153 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6154 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6155 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006156 Error(E, "invalid register operand");
6157 return MatchOperand_ParseFail;
6158 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006159 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6160 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6161 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006162 Error(E, "consecutive register numbers expected");
6163 return MatchOperand_ParseFail;
6164 }
6165
6166 Regs.push_back(RegNo);
6167 }
6168
6169 if (Parser.getTok().is(AsmToken::Minus))
6170 RegRange = true;
6171
6172 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6173 !Parser.getTok().isNot(AsmToken::Comma)) {
6174 Error(E, "',' or '-' expected");
6175 return MatchOperand_ParseFail;
6176 }
6177
6178 Lex(); // Consume comma or minus
6179 if (Parser.getTok().isNot(AsmToken::Dollar))
6180 break;
6181
6182 PrevReg = RegNo;
6183 }
6184
6185 SMLoc E = Parser.getTok().getLoc();
6186 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6187 parseMemOperand(Operands);
6188 return MatchOperand_Success;
6189}
6190
Alex Bradbury58eba092016-11-01 16:32:05 +00006191OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006192MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6193 MCAsmParser &Parser = getParser();
6194
6195 SMLoc S = Parser.getTok().getLoc();
6196 if (parseAnyRegister(Operands) != MatchOperand_Success)
6197 return MatchOperand_ParseFail;
6198
6199 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006200 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006201
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006202 Operands.pop_back();
6203 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006204 return MatchOperand_Success;
6205}
6206
Alex Bradbury58eba092016-11-01 16:32:05 +00006207OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006208MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6209 MCAsmParser &Parser = getParser();
6210 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6211 SmallVector<unsigned, 10> Regs;
6212
6213 if (Parser.getTok().isNot(AsmToken::Dollar))
6214 return MatchOperand_ParseFail;
6215
6216 SMLoc S = Parser.getTok().getLoc();
6217
6218 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6219 return MatchOperand_ParseFail;
6220
6221 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6222 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6223 Regs.push_back(RegNo);
6224
6225 SMLoc E = Parser.getTok().getLoc();
6226 if (Parser.getTok().isNot(AsmToken::Comma)) {
6227 Error(E, "',' expected");
6228 return MatchOperand_ParseFail;
6229 }
6230
6231 // Remove comma.
6232 Parser.Lex();
6233
6234 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6235 return MatchOperand_ParseFail;
6236
6237 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6238 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6239 Regs.push_back(RegNo);
6240
6241 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6242
6243 return MatchOperand_Success;
6244}
6245
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006246/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6247/// either this.
6248/// ::= '(', register, ')'
6249/// handle it before we iterate so we don't get tripped up by the lack of
6250/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006251bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006252 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006253 if (getLexer().is(AsmToken::LParen)) {
6254 Operands.push_back(
6255 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6256 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006257 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006258 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006259 return Error(Loc, "unexpected token in argument list");
6260 }
6261 if (Parser.getTok().isNot(AsmToken::RParen)) {
6262 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006263 return Error(Loc, "unexpected token, expected ')'");
6264 }
6265 Operands.push_back(
6266 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6267 Parser.Lex();
6268 }
6269 return false;
6270}
6271
6272/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6273/// either one of these.
6274/// ::= '[', register, ']'
6275/// ::= '[', integer, ']'
6276/// handle it before we iterate so we don't get tripped up by the lack of
6277/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006278bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006279 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006280 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006281 if (getLexer().is(AsmToken::LBrac)) {
6282 Operands.push_back(
6283 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6284 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006285 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006286 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006287 return Error(Loc, "unexpected token in argument list");
6288 }
6289 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6290 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006291 return Error(Loc, "unexpected token, expected ']'");
6292 }
6293 Operands.push_back(
6294 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6295 Parser.Lex();
6296 }
6297 return false;
6298}
6299
David Blaikie960ea3f2014-06-08 16:18:35 +00006300bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6301 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006302 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006303 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006304
6305 // We have reached first instruction, module directive are now forbidden.
6306 getTargetStreamer().forbidModuleDirective();
6307
Vladimir Medic74593e62013-07-17 15:00:42 +00006308 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006309 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006310 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006311 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006312 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006313 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006314
6315 // Read the remaining operands.
6316 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6317 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006318 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006319 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006320 return Error(Loc, "unexpected token in argument list");
6321 }
Toma Tabacu13964452014-09-04 13:23:44 +00006322 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006323 return true;
6324 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006325
Jack Carterd0bd6422013-04-18 00:41:53 +00006326 while (getLexer().is(AsmToken::Comma)) {
6327 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006328 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006329 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006330 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006331 return Error(Loc, "unexpected token in argument list");
6332 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006333 // Parse bracket and parenthesis suffixes before we iterate
6334 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006335 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006336 return true;
6337 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006338 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006339 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006340 }
6341 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006342 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6343 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006344 return Error(Loc, "unexpected token in argument list");
6345 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006346 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006347 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006348}
6349
Nirav Dave996fc132016-05-05 14:15:46 +00006350// FIXME: Given that these have the same name, these should both be
6351// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006352bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006353 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006354 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006355}
6356
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006357bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006358 return Error(Loc, ErrorMsg);
6359}
6360
Jack Carter0b744b32012-10-04 02:29:46 +00006361bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006362 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006363 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006364
6365 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006366 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006367
6368 Parser.Lex(); // Eat "noat".
6369
Jack Carterd0bd6422013-04-18 00:41:53 +00006370 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006371 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006372 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006373 return false;
6374 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006375
6376 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006377 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006378 return false;
6379}
Jack Carterd0bd6422013-04-18 00:41:53 +00006380
Jack Carter0b744b32012-10-04 02:29:46 +00006381bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006382 // Line can be: ".set at", which sets $at to $1
6383 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006384 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006385 Parser.Lex(); // Eat "at".
6386
Jack Carter0b744b32012-10-04 02:29:46 +00006387 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006388 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006389 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006390
6391 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006392 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006393 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006394 }
6395
6396 if (getLexer().isNot(AsmToken::Equal)) {
6397 reportParseError("unexpected token, expected equals sign");
6398 return false;
6399 }
6400 Parser.Lex(); // Eat "=".
6401
6402 if (getLexer().isNot(AsmToken::Dollar)) {
6403 if (getLexer().is(AsmToken::EndOfStatement)) {
6404 reportParseError("no register specified");
6405 return false;
6406 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006407 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006408 return false;
6409 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006410 }
6411 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006412
Toma Tabacu16a74492015-02-13 10:30:57 +00006413 // Find out what "reg" is.
6414 unsigned AtRegNo;
6415 const AsmToken &Reg = Parser.getTok();
6416 if (Reg.is(AsmToken::Identifier)) {
6417 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6418 } else if (Reg.is(AsmToken::Integer)) {
6419 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006420 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006421 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006422 return false;
6423 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006424
6425 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006426 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006427 reportParseError("invalid register");
6428 return false;
6429 }
6430 Parser.Lex(); // Eat "reg".
6431
6432 // If this is not the end of the statement, report an error.
6433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6434 reportParseError("unexpected token, expected end of statement");
6435 return false;
6436 }
6437
6438 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6439
6440 Parser.Lex(); // Consume the EndOfStatement.
6441 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006442}
6443
6444bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006445 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006446 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006447 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006449 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006450 return false;
6451 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006452 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006453 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006454 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006455 return false;
6456}
6457
6458bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006459 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006460 Parser.Lex();
6461 // If this is not the end of the statement, report an error.
6462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006463 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006464 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006465 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006466 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006467 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006468 Parser.Lex(); // Consume the EndOfStatement.
6469 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006470}
6471
6472bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006473 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006474 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006475 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006476 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006477 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006478 return false;
6479 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006480 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006481 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006482 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006483 return false;
6484}
6485
6486bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006487 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006488 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006489 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006491 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006492 return false;
6493 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006494 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006495 reportParseError("`noreorder' must be set before `nomacro'");
6496 return false;
6497 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006498 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006499 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006500 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006501 return false;
6502}
Jack Carterd76b2372013-03-21 21:44:16 +00006503
Daniel Sanders44934432014-08-07 12:03:36 +00006504bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006505 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006506 Parser.Lex();
6507
6508 // If this is not the end of the statement, report an error.
6509 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006510 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006511
6512 setFeatureBits(Mips::FeatureMSA, "msa");
6513 getTargetStreamer().emitDirectiveSetMsa();
6514 return false;
6515}
6516
6517bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006518 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006519 Parser.Lex();
6520
6521 // If this is not the end of the statement, report an error.
6522 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006523 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006524
6525 clearFeatureBits(Mips::FeatureMSA, "msa");
6526 getTargetStreamer().emitDirectiveSetNoMsa();
6527 return false;
6528}
6529
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006530bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006531 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006532 Parser.Lex(); // Eat "nodsp".
6533
6534 // If this is not the end of the statement, report an error.
6535 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6536 reportParseError("unexpected token, expected end of statement");
6537 return false;
6538 }
6539
6540 clearFeatureBits(Mips::FeatureDSP, "dsp");
6541 getTargetStreamer().emitDirectiveSetNoDsp();
6542 return false;
6543}
6544
Toma Tabacucc2502d2014-11-04 17:18:07 +00006545bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006546 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006547 Parser.Lex(); // Eat "mips16".
6548
Jack Carter39536722014-01-22 23:08:42 +00006549 // If this is not the end of the statement, report an error.
6550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006551 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006552 return false;
6553 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006554
6555 setFeatureBits(Mips::FeatureMips16, "mips16");
6556 getTargetStreamer().emitDirectiveSetMips16();
6557 Parser.Lex(); // Consume the EndOfStatement.
6558 return false;
6559}
6560
6561bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006562 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006563 Parser.Lex(); // Eat "nomips16".
6564
6565 // If this is not the end of the statement, report an error.
6566 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6567 reportParseError("unexpected token, expected end of statement");
6568 return false;
6569 }
6570
6571 clearFeatureBits(Mips::FeatureMips16, "mips16");
6572 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006573 Parser.Lex(); // Consume the EndOfStatement.
6574 return false;
6575}
6576
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006577bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006578 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006579 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006580 // Line can be: .set fp=32
6581 // .set fp=xx
6582 // .set fp=64
6583 Parser.Lex(); // Eat fp token
6584 AsmToken Tok = Parser.getTok();
6585 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006586 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006587 return false;
6588 }
6589 Parser.Lex(); // Eat '=' token.
6590 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006591
6592 if (!parseFpABIValue(FpAbiVal, ".set"))
6593 return false;
6594
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006595 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006596 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006597 return false;
6598 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006599 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006600 Parser.Lex(); // Consume the EndOfStatement.
6601 return false;
6602}
6603
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006604bool MipsAsmParser::parseSetOddSPRegDirective() {
6605 MCAsmParser &Parser = getParser();
6606
6607 Parser.Lex(); // Eat "oddspreg".
6608 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6609 reportParseError("unexpected token, expected end of statement");
6610 return false;
6611 }
6612
6613 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6614 getTargetStreamer().emitDirectiveSetOddSPReg();
6615 return false;
6616}
6617
6618bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6619 MCAsmParser &Parser = getParser();
6620
6621 Parser.Lex(); // Eat "nooddspreg".
6622 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6623 reportParseError("unexpected token, expected end of statement");
6624 return false;
6625 }
6626
6627 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6628 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6629 return false;
6630}
6631
Simon Dardis805f1e02017-07-11 21:28:36 +00006632bool MipsAsmParser::parseSetMtDirective() {
6633 MCAsmParser &Parser = getParser();
6634 Parser.Lex(); // Eat "mt".
6635
6636 // If this is not the end of the statement, report an error.
6637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6638 reportParseError("unexpected token, expected end of statement");
6639 return false;
6640 }
6641
6642 setFeatureBits(Mips::FeatureMT, "mt");
6643 getTargetStreamer().emitDirectiveSetMt();
6644 Parser.Lex(); // Consume the EndOfStatement.
6645 return false;
6646}
6647
6648bool MipsAsmParser::parseSetNoMtDirective() {
6649 MCAsmParser &Parser = getParser();
6650 Parser.Lex(); // Eat "nomt".
6651
6652 // If this is not the end of the statement, report an error.
6653 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6654 reportParseError("unexpected token, expected end of statement");
6655 return false;
6656 }
6657
6658 clearFeatureBits(Mips::FeatureMT, "mt");
6659
6660 getTargetStreamer().emitDirectiveSetNoMt();
6661 Parser.Lex(); // Consume the EndOfStatement.
6662 return false;
6663}
6664
Toma Tabacu9db22db2014-09-09 10:15:38 +00006665bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006666 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006667 SMLoc Loc = getLexer().getLoc();
6668
6669 Parser.Lex();
6670 if (getLexer().isNot(AsmToken::EndOfStatement))
6671 return reportParseError("unexpected token, expected end of statement");
6672
6673 // Always keep an element on the options "stack" to prevent the user
6674 // from changing the initial options. This is how we remember them.
6675 if (AssemblerOptions.size() == 2)
6676 return reportParseError(Loc, ".set pop with no .set push");
6677
Akira Hatanakab11ef082015-11-14 06:35:56 +00006678 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006679 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006680 setAvailableFeatures(
6681 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6682 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006683
6684 getTargetStreamer().emitDirectiveSetPop();
6685 return false;
6686}
6687
6688bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006689 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006690 Parser.Lex();
6691 if (getLexer().isNot(AsmToken::EndOfStatement))
6692 return reportParseError("unexpected token, expected end of statement");
6693
6694 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006695 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006696 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006697
6698 getTargetStreamer().emitDirectiveSetPush();
6699 return false;
6700}
6701
Toma Tabacu29696502015-06-02 09:48:04 +00006702bool MipsAsmParser::parseSetSoftFloatDirective() {
6703 MCAsmParser &Parser = getParser();
6704 Parser.Lex();
6705 if (getLexer().isNot(AsmToken::EndOfStatement))
6706 return reportParseError("unexpected token, expected end of statement");
6707
6708 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6709 getTargetStreamer().emitDirectiveSetSoftFloat();
6710 return false;
6711}
6712
6713bool MipsAsmParser::parseSetHardFloatDirective() {
6714 MCAsmParser &Parser = getParser();
6715 Parser.Lex();
6716 if (getLexer().isNot(AsmToken::EndOfStatement))
6717 return reportParseError("unexpected token, expected end of statement");
6718
6719 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6720 getTargetStreamer().emitDirectiveSetHardFloat();
6721 return false;
6722}
6723
Jack Carterd76b2372013-03-21 21:44:16 +00006724bool MipsAsmParser::parseSetAssignment() {
6725 StringRef Name;
6726 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006727 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006728
6729 if (Parser.parseIdentifier(Name))
6730 reportParseError("expected identifier after .set");
6731
6732 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006733 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006734 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006735
Jack Carter3b2c96e2014-01-22 23:31:38 +00006736 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006737 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006738
Jim Grosbach6f482002015-05-18 18:43:14 +00006739 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006740 Sym->setVariableValue(Value);
6741
6742 return false;
6743}
Jack Carterd0bd6422013-04-18 00:41:53 +00006744
Toma Tabacu26647792014-09-09 12:52:14 +00006745bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006746 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006747 Parser.Lex();
6748 if (getLexer().isNot(AsmToken::EndOfStatement))
6749 return reportParseError("unexpected token, expected end of statement");
6750
6751 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006752 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006753 setAvailableFeatures(
6754 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6755 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006756 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6757
6758 getTargetStreamer().emitDirectiveSetMips0();
6759 return false;
6760}
6761
Toma Tabacu85618b32014-08-19 14:22:52 +00006762bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006763 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006764 Parser.Lex();
6765 if (getLexer().isNot(AsmToken::Equal))
6766 return reportParseError("unexpected token, expected equals sign");
6767
6768 Parser.Lex();
6769 StringRef Arch;
6770 if (Parser.parseIdentifier(Arch))
6771 return reportParseError("expected arch identifier");
6772
6773 StringRef ArchFeatureName =
6774 StringSwitch<StringRef>(Arch)
6775 .Case("mips1", "mips1")
6776 .Case("mips2", "mips2")
6777 .Case("mips3", "mips3")
6778 .Case("mips4", "mips4")
6779 .Case("mips5", "mips5")
6780 .Case("mips32", "mips32")
6781 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006782 .Case("mips32r3", "mips32r3")
6783 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006784 .Case("mips32r6", "mips32r6")
6785 .Case("mips64", "mips64")
6786 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006787 .Case("mips64r3", "mips64r3")
6788 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006789 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006790 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006791 .Case("r4000", "mips3") // This is an implementation of Mips3.
6792 .Default("");
6793
6794 if (ArchFeatureName.empty())
6795 return reportParseError("unsupported architecture");
6796
6797 selectArch(ArchFeatureName);
6798 getTargetStreamer().emitDirectiveSetArch(Arch);
6799 return false;
6800}
6801
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006802bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006803 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006804 Parser.Lex();
6805 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006806 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006807
Matheus Almeida2852af82014-04-22 10:15:54 +00006808 switch (Feature) {
6809 default:
6810 llvm_unreachable("Unimplemented feature");
6811 case Mips::FeatureDSP:
6812 setFeatureBits(Mips::FeatureDSP, "dsp");
6813 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006814 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006815 case Mips::FeatureDSPR2:
6816 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6817 getTargetStreamer().emitDirectiveSetDspr2();
6818 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006819 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006820 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006821 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006822 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006823 case Mips::FeatureMips1:
6824 selectArch("mips1");
6825 getTargetStreamer().emitDirectiveSetMips1();
6826 break;
6827 case Mips::FeatureMips2:
6828 selectArch("mips2");
6829 getTargetStreamer().emitDirectiveSetMips2();
6830 break;
6831 case Mips::FeatureMips3:
6832 selectArch("mips3");
6833 getTargetStreamer().emitDirectiveSetMips3();
6834 break;
6835 case Mips::FeatureMips4:
6836 selectArch("mips4");
6837 getTargetStreamer().emitDirectiveSetMips4();
6838 break;
6839 case Mips::FeatureMips5:
6840 selectArch("mips5");
6841 getTargetStreamer().emitDirectiveSetMips5();
6842 break;
6843 case Mips::FeatureMips32:
6844 selectArch("mips32");
6845 getTargetStreamer().emitDirectiveSetMips32();
6846 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006847 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006848 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006849 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006850 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006851 case Mips::FeatureMips32r3:
6852 selectArch("mips32r3");
6853 getTargetStreamer().emitDirectiveSetMips32R3();
6854 break;
6855 case Mips::FeatureMips32r5:
6856 selectArch("mips32r5");
6857 getTargetStreamer().emitDirectiveSetMips32R5();
6858 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006859 case Mips::FeatureMips32r6:
6860 selectArch("mips32r6");
6861 getTargetStreamer().emitDirectiveSetMips32R6();
6862 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006863 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006864 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006865 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006866 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006867 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006868 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006869 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006870 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006871 case Mips::FeatureMips64r3:
6872 selectArch("mips64r3");
6873 getTargetStreamer().emitDirectiveSetMips64R3();
6874 break;
6875 case Mips::FeatureMips64r5:
6876 selectArch("mips64r5");
6877 getTargetStreamer().emitDirectiveSetMips64R5();
6878 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006879 case Mips::FeatureMips64r6:
6880 selectArch("mips64r6");
6881 getTargetStreamer().emitDirectiveSetMips64R6();
6882 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006883 }
6884 return false;
6885}
6886
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006887bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006888 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006889 if (getLexer().isNot(AsmToken::Comma)) {
6890 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006891 return Error(Loc, ErrorStr);
6892 }
6893
Matheus Almeida2852af82014-04-22 10:15:54 +00006894 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006895 return true;
6896}
6897
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006898// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6899// In this class, it is only used for .cprestore.
6900// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6901// MipsTargetELFStreamer and MipsAsmParser.
6902bool MipsAsmParser::isPicAndNotNxxAbi() {
6903 return inPicMode() && !(isABI_N32() || isABI_N64());
6904}
6905
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006906bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006907 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006908 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006909
Toma Tabacudde4c462014-11-06 10:02:45 +00006910 if (inMips16Mode()) {
6911 reportParseError(".cpload is not supported in Mips16 mode");
6912 return false;
6913 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006914
David Blaikie960ea3f2014-06-08 16:18:35 +00006915 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006916 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006917 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6918 reportParseError("expected register containing function address");
6919 return false;
6920 }
6921
David Blaikie960ea3f2014-06-08 16:18:35 +00006922 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6923 if (!RegOpnd.isGPRAsmReg()) {
6924 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006925 return false;
6926 }
6927
Toma Tabacudde4c462014-11-06 10:02:45 +00006928 // If this is not the end of the statement, report an error.
6929 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6930 reportParseError("unexpected token, expected end of statement");
6931 return false;
6932 }
6933
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006934 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006935 return false;
6936}
6937
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006938bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6939 MCAsmParser &Parser = getParser();
6940
6941 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6942 // is used in non-PIC mode.
6943
6944 if (inMips16Mode()) {
6945 reportParseError(".cprestore is not supported in Mips16 mode");
6946 return false;
6947 }
6948
6949 // Get the stack offset value.
6950 const MCExpr *StackOffset;
6951 int64_t StackOffsetVal;
6952 if (Parser.parseExpression(StackOffset)) {
6953 reportParseError("expected stack offset value");
6954 return false;
6955 }
6956
6957 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6958 reportParseError("stack offset is not an absolute expression");
6959 return false;
6960 }
6961
6962 if (StackOffsetVal < 0) {
6963 Warning(Loc, ".cprestore with negative stack offset has no effect");
6964 IsCpRestoreSet = false;
6965 } else {
6966 IsCpRestoreSet = true;
6967 CpRestoreOffset = StackOffsetVal;
6968 }
6969
6970 // If this is not the end of the statement, report an error.
6971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6972 reportParseError("unexpected token, expected end of statement");
6973 return false;
6974 }
6975
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006976 if (!getTargetStreamer().emitDirectiveCpRestore(
6977 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006978 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006979 Parser.Lex(); // Consume the EndOfStatement.
6980 return false;
6981}
6982
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006983bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006984 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006985 unsigned FuncReg;
6986 unsigned Save;
6987 bool SaveIsReg = true;
6988
Matheus Almeida7e815762014-06-18 13:08:59 +00006989 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006990 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006991 if (ResTy == MatchOperand_NoMatch) {
6992 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006993 return false;
6994 }
6995
6996 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6997 if (!FuncRegOpnd.isGPRAsmReg()) {
6998 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006999 return false;
7000 }
7001
7002 FuncReg = FuncRegOpnd.getGPR32Reg();
7003 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007004
Toma Tabacu65f10572014-09-16 15:00:52 +00007005 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007006 return true;
7007
Toma Tabacu13964452014-09-04 13:23:44 +00007008 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007009 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007010 const MCExpr *OffsetExpr;
7011 int64_t OffsetVal;
7012 SMLoc ExprLoc = getLexer().getLoc();
7013
7014 if (Parser.parseExpression(OffsetExpr) ||
7015 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7016 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007017 return false;
7018 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007019
7020 Save = OffsetVal;
7021 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007022 } else {
7023 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7024 if (!SaveOpnd.isGPRAsmReg()) {
7025 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007026 return false;
7027 }
7028 Save = SaveOpnd.getGPR32Reg();
7029 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007030
Toma Tabacu65f10572014-09-16 15:00:52 +00007031 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007032 return true;
7033
Toma Tabacu8874eac2015-02-18 13:46:53 +00007034 const MCExpr *Expr;
7035 if (Parser.parseExpression(Expr)) {
7036 reportParseError("expected expression");
7037 return false;
7038 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007039
Toma Tabacu8874eac2015-02-18 13:46:53 +00007040 if (Expr->getKind() != MCExpr::SymbolRef) {
7041 reportParseError("expected symbol");
7042 return false;
7043 }
7044 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7045
Daniel Sandersf173dda2015-09-22 10:50:09 +00007046 CpSaveLocation = Save;
7047 CpSaveLocationIsRegister = SaveIsReg;
7048
Toma Tabacu8874eac2015-02-18 13:46:53 +00007049 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7050 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007051 return false;
7052}
7053
Daniel Sandersf173dda2015-09-22 10:50:09 +00007054bool MipsAsmParser::parseDirectiveCPReturn() {
7055 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7056 CpSaveLocationIsRegister);
7057 return false;
7058}
7059
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007060bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007061 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7063 const AsmToken &Tok = Parser.getTok();
7064
7065 if (Tok.getString() == "2008") {
7066 Parser.Lex();
7067 getTargetStreamer().emitDirectiveNaN2008();
7068 return false;
7069 } else if (Tok.getString() == "legacy") {
7070 Parser.Lex();
7071 getTargetStreamer().emitDirectiveNaNLegacy();
7072 return false;
7073 }
7074 }
7075 // If we don't recognize the option passed to the .nan
7076 // directive (e.g. no option or unknown option), emit an error.
7077 reportParseError("invalid option in .nan directive");
7078 return false;
7079}
7080
Jack Carter0b744b32012-10-04 02:29:46 +00007081bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007082 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00007083 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00007084 const AsmToken &Tok = Parser.getTok();
7085
7086 if (Tok.getString() == "noat") {
7087 return parseSetNoAtDirective();
7088 } else if (Tok.getString() == "at") {
7089 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00007090 } else if (Tok.getString() == "arch") {
7091 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00007092 } else if (Tok.getString() == "bopt") {
7093 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
7094 getParser().Lex();
7095 return false;
7096 } else if (Tok.getString() == "nobopt") {
7097 // We're already running in nobopt mode, so nothing to do.
7098 getParser().Lex();
7099 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007100 } else if (Tok.getString() == "fp") {
7101 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007102 } else if (Tok.getString() == "oddspreg") {
7103 return parseSetOddSPRegDirective();
7104 } else if (Tok.getString() == "nooddspreg") {
7105 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00007106 } else if (Tok.getString() == "pop") {
7107 return parseSetPopDirective();
7108 } else if (Tok.getString() == "push") {
7109 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00007110 } else if (Tok.getString() == "reorder") {
7111 return parseSetReorderDirective();
7112 } else if (Tok.getString() == "noreorder") {
7113 return parseSetNoReorderDirective();
7114 } else if (Tok.getString() == "macro") {
7115 return parseSetMacroDirective();
7116 } else if (Tok.getString() == "nomacro") {
7117 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00007118 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00007119 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007120 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00007121 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007122 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007123 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007124 getTargetStreamer().emitDirectiveSetNoMicroMips();
7125 Parser.eatToEndOfStatement();
7126 return false;
7127 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007128 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00007129 } else if (Tok.getString() == "mips0") {
7130 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00007131 } else if (Tok.getString() == "mips1") {
7132 return parseSetFeature(Mips::FeatureMips1);
7133 } else if (Tok.getString() == "mips2") {
7134 return parseSetFeature(Mips::FeatureMips2);
7135 } else if (Tok.getString() == "mips3") {
7136 return parseSetFeature(Mips::FeatureMips3);
7137 } else if (Tok.getString() == "mips4") {
7138 return parseSetFeature(Mips::FeatureMips4);
7139 } else if (Tok.getString() == "mips5") {
7140 return parseSetFeature(Mips::FeatureMips5);
7141 } else if (Tok.getString() == "mips32") {
7142 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00007143 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007144 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007145 } else if (Tok.getString() == "mips32r3") {
7146 return parseSetFeature(Mips::FeatureMips32r3);
7147 } else if (Tok.getString() == "mips32r5") {
7148 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007149 } else if (Tok.getString() == "mips32r6") {
7150 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007151 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007152 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007153 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007154 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007155 } else if (Tok.getString() == "mips64r3") {
7156 return parseSetFeature(Mips::FeatureMips64r3);
7157 } else if (Tok.getString() == "mips64r5") {
7158 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007159 } else if (Tok.getString() == "mips64r6") {
7160 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00007161 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007162 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00007163 } else if (Tok.getString() == "dspr2") {
7164 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00007165 } else if (Tok.getString() == "nodsp") {
7166 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00007167 } else if (Tok.getString() == "msa") {
7168 return parseSetMsaDirective();
7169 } else if (Tok.getString() == "nomsa") {
7170 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00007171 } else if (Tok.getString() == "mt") {
7172 return parseSetMtDirective();
7173 } else if (Tok.getString() == "nomt") {
7174 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00007175 } else if (Tok.getString() == "softfloat") {
7176 return parseSetSoftFloatDirective();
7177 } else if (Tok.getString() == "hardfloat") {
7178 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00007179 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00007180 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00007181 parseSetAssignment();
7182 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00007183 }
Jack Carter07c818d2013-01-25 01:31:34 +00007184
Jack Carter0b744b32012-10-04 02:29:46 +00007185 return true;
7186}
7187
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007188/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007189/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007190bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007191 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007192 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007193 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007194 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007195 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007196 return true;
7197
7198 getParser().getStreamer().EmitValue(Value, Size);
7199
7200 if (getLexer().is(AsmToken::EndOfStatement))
7201 break;
7202
Jack Carter07c818d2013-01-25 01:31:34 +00007203 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007204 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007205 Parser.Lex();
7206 }
7207 }
7208
7209 Parser.Lex();
7210 return false;
7211}
7212
Vladimir Medic4c299852013-11-06 11:27:05 +00007213/// parseDirectiveGpWord
7214/// ::= .gpword local_sym
7215bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007216 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007217 const MCExpr *Value;
7218 // EmitGPRel32Value requires an expression, so we are using base class
7219 // method to evaluate the expression.
7220 if (getParser().parseExpression(Value))
7221 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007222 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007223
Vladimir Medice10c1122013-11-13 13:18:04 +00007224 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007225 return Error(getLexer().getLoc(),
7226 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007227 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007228 return false;
7229}
7230
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007231/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007232/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007233bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007234 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007235 const MCExpr *Value;
7236 // EmitGPRel64Value requires an expression, so we are using base class
7237 // method to evaluate the expression.
7238 if (getParser().parseExpression(Value))
7239 return true;
7240 getParser().getStreamer().EmitGPRel64Value(Value);
7241
7242 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007243 return Error(getLexer().getLoc(),
7244 "unexpected token, expected end of statement");
7245 Parser.Lex(); // Eat EndOfStatement token.
7246 return false;
7247}
7248
7249/// parseDirectiveDtpRelWord
7250/// ::= .dtprelword tls_sym
7251bool MipsAsmParser::parseDirectiveDtpRelWord() {
7252 MCAsmParser &Parser = getParser();
7253 const MCExpr *Value;
7254 // EmitDTPRel32Value requires an expression, so we are using base class
7255 // method to evaluate the expression.
7256 if (getParser().parseExpression(Value))
7257 return true;
7258 getParser().getStreamer().EmitDTPRel32Value(Value);
7259
7260 if (getLexer().isNot(AsmToken::EndOfStatement))
7261 return Error(getLexer().getLoc(),
7262 "unexpected token, expected end of statement");
7263 Parser.Lex(); // Eat EndOfStatement token.
7264 return false;
7265}
7266
7267/// parseDirectiveDtpRelDWord
7268/// ::= .dtpreldword tls_sym
7269bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7270 MCAsmParser &Parser = getParser();
7271 const MCExpr *Value;
7272 // EmitDTPRel64Value requires an expression, so we are using base class
7273 // method to evaluate the expression.
7274 if (getParser().parseExpression(Value))
7275 return true;
7276 getParser().getStreamer().EmitDTPRel64Value(Value);
7277
7278 if (getLexer().isNot(AsmToken::EndOfStatement))
7279 return Error(getLexer().getLoc(),
7280 "unexpected token, expected end of statement");
7281 Parser.Lex(); // Eat EndOfStatement token.
7282 return false;
7283}
7284
7285/// parseDirectiveTpRelWord
7286/// ::= .tprelword tls_sym
7287bool MipsAsmParser::parseDirectiveTpRelWord() {
7288 MCAsmParser &Parser = getParser();
7289 const MCExpr *Value;
7290 // EmitTPRel32Value requires an expression, so we are using base class
7291 // method to evaluate the expression.
7292 if (getParser().parseExpression(Value))
7293 return true;
7294 getParser().getStreamer().EmitTPRel32Value(Value);
7295
7296 if (getLexer().isNot(AsmToken::EndOfStatement))
7297 return Error(getLexer().getLoc(),
7298 "unexpected token, expected end of statement");
7299 Parser.Lex(); // Eat EndOfStatement token.
7300 return false;
7301}
7302
7303/// parseDirectiveTpRelDWord
7304/// ::= .tpreldword tls_sym
7305bool MipsAsmParser::parseDirectiveTpRelDWord() {
7306 MCAsmParser &Parser = getParser();
7307 const MCExpr *Value;
7308 // EmitTPRel64Value requires an expression, so we are using base class
7309 // method to evaluate the expression.
7310 if (getParser().parseExpression(Value))
7311 return true;
7312 getParser().getStreamer().EmitTPRel64Value(Value);
7313
7314 if (getLexer().isNot(AsmToken::EndOfStatement))
7315 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007316 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007317 Parser.Lex(); // Eat EndOfStatement token.
7318 return false;
7319}
7320
Jack Carter0cd3c192014-01-06 23:27:31 +00007321bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007322 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007323 // Get the option token.
7324 AsmToken Tok = Parser.getTok();
7325 // At the moment only identifiers are supported.
7326 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007327 return Error(Parser.getTok().getLoc(),
7328 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007329 }
7330
7331 StringRef Option = Tok.getIdentifier();
7332
7333 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007334 // MipsAsmParser needs to know if the current PIC mode changes.
7335 IsPicEnabled = false;
7336
Jack Carter0cd3c192014-01-06 23:27:31 +00007337 getTargetStreamer().emitDirectiveOptionPic0();
7338 Parser.Lex();
7339 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007340 return Error(Parser.getTok().getLoc(),
7341 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007342 }
7343 return false;
7344 }
7345
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007346 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007347 // MipsAsmParser needs to know if the current PIC mode changes.
7348 IsPicEnabled = true;
7349
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007350 getTargetStreamer().emitDirectiveOptionPic2();
7351 Parser.Lex();
7352 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007353 return Error(Parser.getTok().getLoc(),
7354 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007355 }
7356 return false;
7357 }
7358
Jack Carter0cd3c192014-01-06 23:27:31 +00007359 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007360 Warning(Parser.getTok().getLoc(),
7361 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007362 Parser.eatToEndOfStatement();
7363 return false;
7364}
7365
Toma Tabacu9ca50962015-04-16 09:53:47 +00007366/// parseInsnDirective
7367/// ::= .insn
7368bool MipsAsmParser::parseInsnDirective() {
7369 // If this is not the end of the statement, report an error.
7370 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7371 reportParseError("unexpected token, expected end of statement");
7372 return false;
7373 }
7374
7375 // The actual label marking happens in
7376 // MipsELFStreamer::createPendingLabelRelocs().
7377 getTargetStreamer().emitDirectiveInsn();
7378
7379 getParser().Lex(); // Eat EndOfStatement token.
7380 return false;
7381}
7382
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007383/// parseRSectionDirective
7384/// ::= .rdata
7385bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7386 // If this is not the end of the statement, report an error.
7387 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7388 reportParseError("unexpected token, expected end of statement");
7389 return false;
7390 }
7391
7392 MCSection *ELFSection = getContext().getELFSection(
7393 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7394 getParser().getStreamer().SwitchSection(ELFSection);
7395
7396 getParser().Lex(); // Eat EndOfStatement token.
7397 return false;
7398}
7399
Simon Atanasyanbe186202016-02-11 06:45:54 +00007400/// parseSSectionDirective
7401/// ::= .sbss
7402/// ::= .sdata
7403bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7404 // If this is not the end of the statement, report an error.
7405 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7406 reportParseError("unexpected token, expected end of statement");
7407 return false;
7408 }
7409
7410 MCSection *ELFSection = getContext().getELFSection(
7411 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7412 getParser().getStreamer().SwitchSection(ELFSection);
7413
7414 getParser().Lex(); // Eat EndOfStatement token.
7415 return false;
7416}
7417
Daniel Sanders7e527422014-07-10 13:38:23 +00007418/// parseDirectiveModule
7419/// ::= .module oddspreg
7420/// ::= .module nooddspreg
7421/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007422/// ::= .module softfloat
7423/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007424/// ::= .module mt
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007425bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007426 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007427 MCAsmLexer &Lexer = getLexer();
7428 SMLoc L = Lexer.getLoc();
7429
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007430 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007431 // TODO : get a better message.
7432 reportParseError(".module directive must appear before any code");
7433 return false;
7434 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007435
Toma Tabacuc405c822015-01-23 10:40:19 +00007436 StringRef Option;
7437 if (Parser.parseIdentifier(Option)) {
7438 reportParseError("expected .module option identifier");
7439 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007440 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007441
Toma Tabacuc405c822015-01-23 10:40:19 +00007442 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007443 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007444
Toma Tabacu3c499582015-06-25 10:56:57 +00007445 // Synchronize the abiflags information with the FeatureBits information we
7446 // changed above.
7447 getTargetStreamer().updateABIInfo(*this);
7448
7449 // If printing assembly, use the recently updated abiflags information.
7450 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7451 // emitted at the end).
7452 getTargetStreamer().emitDirectiveModuleOddSPReg();
7453
Toma Tabacuc405c822015-01-23 10:40:19 +00007454 // If this is not the end of the statement, report an error.
7455 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7456 reportParseError("unexpected token, expected end of statement");
7457 return false;
7458 }
7459
7460 return false; // parseDirectiveModule has finished successfully.
7461 } else if (Option == "nooddspreg") {
7462 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007463 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007464 }
7465
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007466 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007467
Toma Tabacu3c499582015-06-25 10:56:57 +00007468 // Synchronize the abiflags information with the FeatureBits information we
7469 // changed above.
7470 getTargetStreamer().updateABIInfo(*this);
7471
7472 // If printing assembly, use the recently updated abiflags information.
7473 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7474 // emitted at the end).
7475 getTargetStreamer().emitDirectiveModuleOddSPReg();
7476
Toma Tabacuc405c822015-01-23 10:40:19 +00007477 // If this is not the end of the statement, report an error.
7478 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7479 reportParseError("unexpected token, expected end of statement");
7480 return false;
7481 }
7482
7483 return false; // parseDirectiveModule has finished successfully.
7484 } else if (Option == "fp") {
7485 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007486 } else if (Option == "softfloat") {
7487 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7488
7489 // Synchronize the ABI Flags information with the FeatureBits information we
7490 // updated above.
7491 getTargetStreamer().updateABIInfo(*this);
7492
7493 // If printing assembly, use the recently updated ABI Flags information.
7494 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7495 // emitted later).
7496 getTargetStreamer().emitDirectiveModuleSoftFloat();
7497
7498 // If this is not the end of the statement, report an error.
7499 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7500 reportParseError("unexpected token, expected end of statement");
7501 return false;
7502 }
7503
7504 return false; // parseDirectiveModule has finished successfully.
7505 } else if (Option == "hardfloat") {
7506 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7507
7508 // Synchronize the ABI Flags information with the FeatureBits information we
7509 // updated above.
7510 getTargetStreamer().updateABIInfo(*this);
7511
7512 // If printing assembly, use the recently updated ABI Flags information.
7513 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7514 // emitted later).
7515 getTargetStreamer().emitDirectiveModuleHardFloat();
7516
7517 // If this is not the end of the statement, report an error.
7518 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7519 reportParseError("unexpected token, expected end of statement");
7520 return false;
7521 }
7522
7523 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007524 } else if (Option == "mt") {
7525 setModuleFeatureBits(Mips::FeatureMT, "mt");
7526
7527 // Synchronize the ABI Flags information with the FeatureBits information we
7528 // updated above.
7529 getTargetStreamer().updateABIInfo(*this);
7530
Simon Dardisd9611922017-07-11 21:36:58 +00007531 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007532 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7533 // emitted later).
7534 getTargetStreamer().emitDirectiveModuleMT();
7535
7536 // If this is not the end of the statement, report an error.
7537 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7538 reportParseError("unexpected token, expected end of statement");
7539 return false;
7540 }
7541
7542 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007543 } else {
7544 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7545 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007546}
7547
7548/// parseDirectiveModuleFP
7549/// ::= =32
7550/// ::= =xx
7551/// ::= =64
7552bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007553 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007554 MCAsmLexer &Lexer = getLexer();
7555
7556 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007557 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007558 return false;
7559 }
7560 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007561
Daniel Sanders7e527422014-07-10 13:38:23 +00007562 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007563 if (!parseFpABIValue(FpABI, ".module"))
7564 return false;
7565
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007566 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007567 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007568 return false;
7569 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007570
Toma Tabacua64e5402015-06-25 12:44:38 +00007571 // Synchronize the abiflags information with the FeatureBits information we
7572 // changed above.
7573 getTargetStreamer().updateABIInfo(*this);
7574
7575 // If printing assembly, use the recently updated abiflags information.
7576 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7577 // emitted at the end).
7578 getTargetStreamer().emitDirectiveModuleFP();
7579
Daniel Sanders7e527422014-07-10 13:38:23 +00007580 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007581 return false;
7582}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007583
Daniel Sanders7e527422014-07-10 13:38:23 +00007584bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007585 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007586 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007587 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007588 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007589
7590 if (Lexer.is(AsmToken::Identifier)) {
7591 StringRef Value = Parser.getTok().getString();
7592 Parser.Lex();
7593
7594 if (Value != "xx") {
7595 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7596 return false;
7597 }
7598
7599 if (!isABI_O32()) {
7600 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7601 return false;
7602 }
7603
Daniel Sanders7e527422014-07-10 13:38:23 +00007604 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007605 if (ModuleLevelOptions) {
7606 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7607 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7608 } else {
7609 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7610 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7611 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007612 return true;
7613 }
7614
7615 if (Lexer.is(AsmToken::Integer)) {
7616 unsigned Value = Parser.getTok().getIntVal();
7617 Parser.Lex();
7618
7619 if (Value != 32 && Value != 64) {
7620 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7621 return false;
7622 }
7623
7624 if (Value == 32) {
7625 if (!isABI_O32()) {
7626 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7627 return false;
7628 }
7629
Daniel Sanders7e527422014-07-10 13:38:23 +00007630 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007631 if (ModuleLevelOptions) {
7632 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7633 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7634 } else {
7635 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7636 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7637 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007638 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007639 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007640 if (ModuleLevelOptions) {
7641 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7642 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7643 } else {
7644 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7645 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7646 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007647 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007648
Daniel Sanders7e527422014-07-10 13:38:23 +00007649 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007650 }
7651
7652 return false;
7653}
7654
Jack Carter0b744b32012-10-04 02:29:46 +00007655bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007656 // This returns false if this function recognizes the directive
7657 // regardless of whether it is successfully handles or reports an
7658 // error. Otherwise it returns true to give the generic parser a
7659 // chance at recognizing it.
7660
Rafael Espindola961d4692014-11-11 05:18:41 +00007661 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007662 StringRef IDVal = DirectiveID.getString();
7663
Nirav Dave996fc132016-05-05 14:15:46 +00007664 if (IDVal == ".cpload") {
7665 parseDirectiveCpLoad(DirectiveID.getLoc());
7666 return false;
7667 }
7668 if (IDVal == ".cprestore") {
7669 parseDirectiveCpRestore(DirectiveID.getLoc());
7670 return false;
7671 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007672 if (IDVal == ".dword") {
7673 parseDataDirective(8, DirectiveID.getLoc());
7674 return false;
7675 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007676 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007677 StringRef SymbolName;
7678
7679 if (Parser.parseIdentifier(SymbolName)) {
7680 reportParseError("expected identifier after .ent");
7681 return false;
7682 }
7683
7684 // There's an undocumented extension that allows an integer to
7685 // follow the name of the procedure which AFAICS is ignored by GAS.
7686 // Example: .ent foo,2
7687 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7688 if (getLexer().isNot(AsmToken::Comma)) {
7689 // Even though we accept this undocumented extension for compatibility
7690 // reasons, the additional integer argument does not actually change
7691 // the behaviour of the '.ent' directive, so we would like to discourage
7692 // its use. We do this by not referring to the extended version in
7693 // error messages which are not directly related to its use.
7694 reportParseError("unexpected token, expected end of statement");
7695 return false;
7696 }
7697 Parser.Lex(); // Eat the comma.
7698 const MCExpr *DummyNumber;
7699 int64_t DummyNumberVal;
7700 // If the user was explicitly trying to use the extended version,
7701 // we still give helpful extension-related error messages.
7702 if (Parser.parseExpression(DummyNumber)) {
7703 reportParseError("expected number after comma");
7704 return false;
7705 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007706 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007707 reportParseError("expected an absolute expression after comma");
7708 return false;
7709 }
7710 }
7711
7712 // If this is not the end of the statement, report an error.
7713 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7714 reportParseError("unexpected token, expected end of statement");
7715 return false;
7716 }
7717
Jim Grosbach6f482002015-05-18 18:43:14 +00007718 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007719
7720 getTargetStreamer().emitDirectiveEnt(*Sym);
7721 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007722 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007723 return false;
7724 }
7725
Jack Carter07c818d2013-01-25 01:31:34 +00007726 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007727 StringRef SymbolName;
7728
7729 if (Parser.parseIdentifier(SymbolName)) {
7730 reportParseError("expected identifier after .end");
7731 return false;
7732 }
7733
7734 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7735 reportParseError("unexpected token, expected end of statement");
7736 return false;
7737 }
7738
7739 if (CurrentFn == nullptr) {
7740 reportParseError(".end used without .ent");
7741 return false;
7742 }
7743
7744 if ((SymbolName != CurrentFn->getName())) {
7745 reportParseError(".end symbol does not match .ent symbol");
7746 return false;
7747 }
7748
7749 getTargetStreamer().emitDirectiveEnd(SymbolName);
7750 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007751 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007752 return false;
7753 }
7754
Jack Carter07c818d2013-01-25 01:31:34 +00007755 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007756 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7757 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007758 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007759 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7760 reportParseError("expected stack register");
7761 return false;
7762 }
7763
7764 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7765 if (!StackRegOpnd.isGPRAsmReg()) {
7766 reportParseError(StackRegOpnd.getStartLoc(),
7767 "expected general purpose register");
7768 return false;
7769 }
7770 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7771
7772 if (Parser.getTok().is(AsmToken::Comma))
7773 Parser.Lex();
7774 else {
7775 reportParseError("unexpected token, expected comma");
7776 return false;
7777 }
7778
7779 // Parse the frame size.
7780 const MCExpr *FrameSize;
7781 int64_t FrameSizeVal;
7782
7783 if (Parser.parseExpression(FrameSize)) {
7784 reportParseError("expected frame size value");
7785 return false;
7786 }
7787
Jim Grosbach13760bd2015-05-30 01:25:56 +00007788 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007789 reportParseError("frame size not an absolute expression");
7790 return false;
7791 }
7792
7793 if (Parser.getTok().is(AsmToken::Comma))
7794 Parser.Lex();
7795 else {
7796 reportParseError("unexpected token, expected comma");
7797 return false;
7798 }
7799
7800 // Parse the return register.
7801 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007802 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007803 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7804 reportParseError("expected return register");
7805 return false;
7806 }
7807
7808 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7809 if (!ReturnRegOpnd.isGPRAsmReg()) {
7810 reportParseError(ReturnRegOpnd.getStartLoc(),
7811 "expected general purpose register");
7812 return false;
7813 }
7814
7815 // If this is not the end of the statement, report an error.
7816 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7817 reportParseError("unexpected token, expected end of statement");
7818 return false;
7819 }
7820
7821 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7822 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007823 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007824 return false;
7825 }
7826
Jack Carter07c818d2013-01-25 01:31:34 +00007827 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007828 parseDirectiveSet();
7829 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007830 }
7831
Daniel Sandersd97a6342014-08-13 10:07:34 +00007832 if (IDVal == ".mask" || IDVal == ".fmask") {
7833 // .mask bitmask, frame_offset
7834 // bitmask: One bit for each register used.
7835 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7836 // first register is expected to be saved.
7837 // Examples:
7838 // .mask 0x80000000, -4
7839 // .fmask 0x80000000, -4
7840 //
Jack Carterbe332172012-09-07 00:48:02 +00007841
Daniel Sandersd97a6342014-08-13 10:07:34 +00007842 // Parse the bitmask
7843 const MCExpr *BitMask;
7844 int64_t BitMaskVal;
7845
7846 if (Parser.parseExpression(BitMask)) {
7847 reportParseError("expected bitmask value");
7848 return false;
7849 }
7850
Jim Grosbach13760bd2015-05-30 01:25:56 +00007851 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007852 reportParseError("bitmask not an absolute expression");
7853 return false;
7854 }
7855
7856 if (Parser.getTok().is(AsmToken::Comma))
7857 Parser.Lex();
7858 else {
7859 reportParseError("unexpected token, expected comma");
7860 return false;
7861 }
7862
7863 // Parse the frame_offset
7864 const MCExpr *FrameOffset;
7865 int64_t FrameOffsetVal;
7866
7867 if (Parser.parseExpression(FrameOffset)) {
7868 reportParseError("expected frame offset value");
7869 return false;
7870 }
7871
Jim Grosbach13760bd2015-05-30 01:25:56 +00007872 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007873 reportParseError("frame offset not an absolute expression");
7874 return false;
7875 }
7876
7877 // If this is not the end of the statement, report an error.
7878 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7879 reportParseError("unexpected token, expected end of statement");
7880 return false;
7881 }
7882
7883 if (IDVal == ".mask")
7884 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7885 else
7886 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007887 return false;
7888 }
7889
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007890 if (IDVal == ".nan")
7891 return parseDirectiveNaN();
7892
Jack Carter07c818d2013-01-25 01:31:34 +00007893 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007894 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007895 return false;
7896 }
7897
Rafael Espindolab59fb732014-03-28 18:50:26 +00007898 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007899 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007900 return false;
7901 }
7902
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007903 if (IDVal == ".dtprelword") {
7904 parseDirectiveDtpRelWord();
7905 return false;
7906 }
7907
7908 if (IDVal == ".dtpreldword") {
7909 parseDirectiveDtpRelDWord();
7910 return false;
7911 }
7912
7913 if (IDVal == ".tprelword") {
7914 parseDirectiveTpRelWord();
7915 return false;
7916 }
7917
7918 if (IDVal == ".tpreldword") {
7919 parseDirectiveTpRelDWord();
7920 return false;
7921 }
7922
Jack Carter07c818d2013-01-25 01:31:34 +00007923 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007924 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007925 return false;
7926 }
7927
Scott Egertond1aeb052016-02-15 16:11:51 +00007928 if (IDVal == ".hword") {
7929 parseDataDirective(2, DirectiveID.getLoc());
7930 return false;
7931 }
7932
Nirav Dave996fc132016-05-05 14:15:46 +00007933 if (IDVal == ".option") {
7934 parseDirectiveOption();
7935 return false;
7936 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007937
7938 if (IDVal == ".abicalls") {
7939 getTargetStreamer().emitDirectiveAbiCalls();
7940 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007941 Error(Parser.getTok().getLoc(),
7942 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007943 }
7944 return false;
7945 }
7946
Nirav Dave996fc132016-05-05 14:15:46 +00007947 if (IDVal == ".cpsetup") {
7948 parseDirectiveCPSetup();
7949 return false;
7950 }
7951 if (IDVal == ".cpreturn") {
7952 parseDirectiveCPReturn();
7953 return false;
7954 }
7955 if (IDVal == ".module") {
7956 parseDirectiveModule();
7957 return false;
7958 }
7959 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7960 parseInternalDirectiveReallowModule();
7961 return false;
7962 }
7963 if (IDVal == ".insn") {
7964 parseInsnDirective();
7965 return false;
7966 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007967 if (IDVal == ".rdata") {
7968 parseRSectionDirective(".rodata");
7969 return false;
7970 }
Nirav Dave996fc132016-05-05 14:15:46 +00007971 if (IDVal == ".sbss") {
7972 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7973 return false;
7974 }
7975 if (IDVal == ".sdata") {
7976 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7977 return false;
7978 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007979
Rafael Espindola870c4e92012-01-11 03:56:41 +00007980 return true;
7981}
7982
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007983bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7984 // If this is not the end of the statement, report an error.
7985 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7986 reportParseError("unexpected token, expected end of statement");
7987 return false;
7988 }
7989
7990 getTargetStreamer().reallowModuleDirective();
7991
7992 getParser().Lex(); // Eat EndOfStatement token.
7993 return false;
7994}
7995
Rafael Espindola870c4e92012-01-11 03:56:41 +00007996extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007997 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7998 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7999 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8000 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008001}
Jack Carterb4dbc172012-09-05 23:34:03 +00008002
8003#define GET_REGISTER_MATCHER
8004#define GET_MATCHER_IMPLEMENTATION
8005#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008006
8007bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8008 // Find the appropriate table for this asm variant.
8009 const MatchEntry *Start, *End;
8010 switch (VariantID) {
8011 default: llvm_unreachable("invalid variant!");
8012 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8013 }
8014 // Search the table.
8015 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8016 return MnemonicRange.first != MnemonicRange.second;
8017}