blob: 5bcddb704a8d573d3695ff6680f8b20b551bd686 [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;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000515
516 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
517 report_fatal_error("microMIPS64R6 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000518 }
519
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000520 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
521 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
522
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool isGP64bit() const {
524 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
525 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000526
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000527 bool isFP64bit() const {
528 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
529 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000530
Eric Christophera5762812015-01-26 17:33:46 +0000531 const MipsABIInfo &getABI() const { return ABI; }
532 bool isABI_N32() const { return ABI.IsN32(); }
533 bool isABI_N64() const { return ABI.IsN64(); }
534 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 bool isABI_FPXX() const {
536 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
537 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000539 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000541 }
542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000546
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000547 bool hasMips1() const {
548 return getSTI().getFeatureBits()[Mips::FeatureMips1];
549 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000550
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000551 bool hasMips2() const {
552 return getSTI().getFeatureBits()[Mips::FeatureMips2];
553 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000554
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000555 bool hasMips3() const {
556 return getSTI().getFeatureBits()[Mips::FeatureMips3];
557 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000558
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000559 bool hasMips4() const {
560 return getSTI().getFeatureBits()[Mips::FeatureMips4];
561 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000562
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000563 bool hasMips5() const {
564 return getSTI().getFeatureBits()[Mips::FeatureMips5];
565 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000566
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000567 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000568 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000570
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000571 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000572 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000574
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000577 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000578
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000579 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000581 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000582
Daniel Sanders17793142015-02-18 16:24:50 +0000583 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000585 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000586
Daniel Sanders17793142015-02-18 16:24:50 +0000587 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000590
Daniel Sanders17793142015-02-18 16:24:50 +0000591 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000592 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000593 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000594
Daniel Sanders17793142015-02-18 16:24:50 +0000595 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000598
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000599 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000602
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000603 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000605 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000606
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000607 bool hasDSP() const {
608 return getSTI().getFeatureBits()[Mips::FeatureDSP];
609 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000610
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000611 bool hasDSPR2() const {
612 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
613 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000614
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000615 bool hasDSPR3() const {
616 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
617 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000618
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000619 bool hasMSA() const {
620 return getSTI().getFeatureBits()[Mips::FeatureMSA];
621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000622
Kai Nackee0245392015-01-27 19:11:28 +0000623 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000624 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000625 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000626
Daniel Sandersa6994442015-08-18 12:33:54 +0000627 bool inPicMode() {
628 return IsPicEnabled;
629 }
630
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000631 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000632 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000633 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000634
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000635 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000636 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000637 }
638
Eric Christophere8ae3e32015-05-07 23:10:21 +0000639 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000640 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000641 }
Simon Dardisae719c52017-07-11 18:03:20 +0000642 bool hasMT() const {
643 return getSTI().getFeatureBits()[Mips::FeatureMT];
644 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000645
Toma Tabacud9d344b2015-04-27 14:05:04 +0000646 /// Warn if RegIndex is the same as the current AT.
647 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000648
649 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000650
651 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000652
653 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
654 AsmToken::TokenKind OperatorToken,
655 MCContext &Ctx) override {
656 switch(OperatorToken) {
657 default:
658 llvm_unreachable("Unknown token");
659 return nullptr;
660 case AsmToken::PercentCall16:
661 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
662 case AsmToken::PercentCall_Hi:
663 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
664 case AsmToken::PercentCall_Lo:
665 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
666 case AsmToken::PercentDtprel_Hi:
667 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
668 case AsmToken::PercentDtprel_Lo:
669 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
670 case AsmToken::PercentGot:
671 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
672 case AsmToken::PercentGot_Disp:
673 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
674 case AsmToken::PercentGot_Hi:
675 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
676 case AsmToken::PercentGot_Lo:
677 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
678 case AsmToken::PercentGot_Ofst:
679 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
680 case AsmToken::PercentGot_Page:
681 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
682 case AsmToken::PercentGottprel:
683 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
684 case AsmToken::PercentGp_Rel:
685 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
686 case AsmToken::PercentHi:
687 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
688 case AsmToken::PercentHigher:
689 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
690 case AsmToken::PercentHighest:
691 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
692 case AsmToken::PercentLo:
693 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
694 case AsmToken::PercentNeg:
695 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
696 case AsmToken::PercentPcrel_Hi:
697 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
698 case AsmToken::PercentPcrel_Lo:
699 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
700 case AsmToken::PercentTlsgd:
701 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
702 case AsmToken::PercentTlsldm:
703 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
704 case AsmToken::PercentTprel_Hi:
705 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
706 case AsmToken::PercentTprel_Lo:
707 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
708 }
709 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000710};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000711
712/// MipsOperand - Instances of this class represent a parsed Mips machine
713/// instruction.
714class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000715public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000716 /// Broad categories of register classes
717 /// The exact class is finalized by the render method.
718 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000719 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000720 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000721 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 RegKind_FCC = 4, /// FCC
723 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
724 RegKind_MSACtrl = 16, /// MSA control registers
725 RegKind_COP2 = 32, /// COP2
726 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
727 /// context).
728 RegKind_CCR = 128, /// CCR
729 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000730 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000731 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 /// Potentially any (e.g. $1)
733 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
734 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000735 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000736 };
737
738private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000739 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000740 k_Immediate, /// An immediate (possibly involving symbol references)
741 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000742 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000743 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000744 k_RegList, /// A physical register list
745 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000746 } Kind;
747
David Blaikie960ea3f2014-06-08 16:18:35 +0000748public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000749 MipsOperand(KindTy K, MipsAsmParser &Parser)
750 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
751
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000752 ~MipsOperand() override {
753 switch (Kind) {
754 case k_Immediate:
755 break;
756 case k_Memory:
757 delete Mem.Base;
758 break;
759 case k_RegList:
760 delete RegList.List;
761 case k_RegisterIndex:
762 case k_Token:
763 case k_RegPair:
764 break;
765 }
766 }
767
David Blaikie960ea3f2014-06-08 16:18:35 +0000768private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000769 /// For diagnostics, and checking the assembler temporary
770 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000771
Eric Christopher8996c5d2013-03-15 00:42:55 +0000772 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000773 const char *Data;
774 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000775 };
776
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 struct RegIdxOp {
778 unsigned Index; /// Index into the register class
779 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000780 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000782 };
783
784 struct ImmOp {
785 const MCExpr *Val;
786 };
787
788 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000790 const MCExpr *Off;
791 };
792
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000793 struct RegListOp {
794 SmallVector<unsigned, 10> *List;
795 };
796
Jack Carterb4dbc172012-09-05 23:34:03 +0000797 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000798 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000800 struct ImmOp Imm;
801 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000802 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000803 };
804
805 SMLoc StartLoc, EndLoc;
806
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000808 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
809 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000810 const MCRegisterInfo *RegInfo,
811 SMLoc S, SMLoc E,
812 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000813 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 Op->RegIdx.Index = Index;
815 Op->RegIdx.RegInfo = RegInfo;
816 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000817 Op->RegIdx.Tok.Data = Str.data();
818 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 Op->StartLoc = S;
820 Op->EndLoc = E;
821 return Op;
822 }
823
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000824public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 /// Coerce the register to GPR32 and return the real register for the current
826 /// target.
827 unsigned getGPR32Reg() const {
828 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000829 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 unsigned ClassID = Mips::GPR32RegClassID;
831 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000832 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000833
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000834 /// Coerce the register to GPR32 and return the real register for the current
835 /// target.
836 unsigned getGPRMM16Reg() const {
837 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
838 unsigned ClassID = Mips::GPR32RegClassID;
839 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
840 }
841
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000842 /// Coerce the register to GPR64 and return the real register for the current
843 /// target.
844 unsigned getGPR64Reg() const {
845 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
846 unsigned ClassID = Mips::GPR64RegClassID;
847 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000848 }
849
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850private:
851 /// Coerce the register to AFGR64 and return the real register for the current
852 /// target.
853 unsigned getAFGR64Reg() const {
854 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
855 if (RegIdx.Index % 2 != 0)
856 AsmParser.Warning(StartLoc, "Float register should be even.");
857 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
858 .getRegister(RegIdx.Index / 2);
859 }
860
861 /// Coerce the register to FGR64 and return the real register for the current
862 /// target.
863 unsigned getFGR64Reg() const {
864 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
865 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
866 .getRegister(RegIdx.Index);
867 }
868
869 /// Coerce the register to FGR32 and return the real register for the current
870 /// target.
871 unsigned getFGR32Reg() const {
872 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
873 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
874 .getRegister(RegIdx.Index);
875 }
876
877 /// Coerce the register to FGRH32 and return the real register for the current
878 /// target.
879 unsigned getFGRH32Reg() const {
880 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
881 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
882 .getRegister(RegIdx.Index);
883 }
884
885 /// Coerce the register to FCC and return the real register for the current
886 /// target.
887 unsigned getFCCReg() const {
888 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
889 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
890 .getRegister(RegIdx.Index);
891 }
892
893 /// Coerce the register to MSA128 and return the real register for the current
894 /// target.
895 unsigned getMSA128Reg() const {
896 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
897 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
898 // identical
899 unsigned ClassID = Mips::MSA128BRegClassID;
900 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
901 }
902
903 /// Coerce the register to MSACtrl and return the real register for the
904 /// current target.
905 unsigned getMSACtrlReg() const {
906 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
907 unsigned ClassID = Mips::MSACtrlRegClassID;
908 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
909 }
910
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000911 /// Coerce the register to COP0 and return the real register for the
912 /// current target.
913 unsigned getCOP0Reg() const {
914 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
915 unsigned ClassID = Mips::COP0RegClassID;
916 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
917 }
918
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000919 /// Coerce the register to COP2 and return the real register for the
920 /// current target.
921 unsigned getCOP2Reg() const {
922 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
923 unsigned ClassID = Mips::COP2RegClassID;
924 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
925 }
926
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000927 /// Coerce the register to COP3 and return the real register for the
928 /// current target.
929 unsigned getCOP3Reg() const {
930 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
931 unsigned ClassID = Mips::COP3RegClassID;
932 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
933 }
934
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 /// Coerce the register to ACC64DSP and return the real register for the
936 /// current target.
937 unsigned getACC64DSPReg() const {
938 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
939 unsigned ClassID = Mips::ACC64DSPRegClassID;
940 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
941 }
942
943 /// Coerce the register to HI32DSP and return the real register for the
944 /// current target.
945 unsigned getHI32DSPReg() const {
946 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
947 unsigned ClassID = Mips::HI32DSPRegClassID;
948 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
949 }
950
951 /// Coerce the register to LO32DSP and return the real register for the
952 /// current target.
953 unsigned getLO32DSPReg() const {
954 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
955 unsigned ClassID = Mips::LO32DSPRegClassID;
956 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
957 }
958
959 /// Coerce the register to CCR and return the real register for the
960 /// current target.
961 unsigned getCCRReg() const {
962 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
963 unsigned ClassID = Mips::CCRRegClassID;
964 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
965 }
966
967 /// Coerce the register to HWRegs and return the real register for the
968 /// current target.
969 unsigned getHWRegsReg() const {
970 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
971 unsigned ClassID = Mips::HWRegsRegClassID;
972 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
973 }
974
975public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000976 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000977 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000978 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000979 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000980 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000981 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000982 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000983 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000984 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000985
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 void addRegOperands(MCInst &Inst, unsigned N) const {
987 llvm_unreachable("Use a custom parser instead");
988 }
989
Daniel Sanders21bce302014-04-01 12:35:23 +0000990 /// Render the operand to an MCInst as a GPR32
991 /// Asserts if the wrong number of operands are requested, or the operand
992 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000993 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
995 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
996 }
997
998 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
999 assert(N == 1 && "Invalid number of operands!");
1000 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1001 }
1002
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001003 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1004 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 }
1007
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001008 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1009 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001010 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001011 }
1012
Jozef Kolek1904fa22014-11-24 14:25:53 +00001013 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1014 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001015 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001016 }
1017
Zoran Jovanovic41688672015-02-10 16:36:20 +00001018 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1019 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001020 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001021 }
1022
Daniel Sanders21bce302014-04-01 12:35:23 +00001023 /// Render the operand to an MCInst as a GPR64
1024 /// Asserts if the wrong number of operands are requested, or the operand
1025 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1027 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001028 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 }
1030
1031 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1032 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001033 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 }
1035
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001036 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1037 assert(N == 1 && "Invalid number of operands!");
1038 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1039 }
1040
1041 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1042 assert(N == 1 && "Invalid number of operands!");
1043 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1044 }
1045
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1047 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001048 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001049 }
1050
1051 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1052 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001053 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001054 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001055 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001056 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001057 AsmParser.getParser().printError(
1058 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1059 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 }
1061
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001062 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
1064 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1065 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1066 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1067 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1068 "registers");
1069 }
1070
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1072 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001073 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 }
1075
1076 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1077 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001078 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001079 }
1080
1081 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1082 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001083 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001084 }
1085
1086 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1087 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001088 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001089 }
1090
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001091 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1092 assert(N == 1 && "Invalid number of operands!");
1093 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1094 }
1095
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1097 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001098 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001099 }
1100
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001101 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1102 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001103 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001104 }
1105
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001106 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1107 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001108 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001109 }
1110
1111 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001113 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001114 }
1115
1116 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001118 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001119 }
1120
1121 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001123 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 }
1125
1126 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001128 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001129 }
1130
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001131 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001132 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001134 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001135 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001136 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001137 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001138 Inst.addOperand(MCOperand::createImm(Imm));
1139 }
1140
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001141 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001142 void addSImmOperands(MCInst &Inst, unsigned N) const {
1143 if (isImm() && !isConstantImm()) {
1144 addExpr(Inst, getImm());
1145 return;
1146 }
1147 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1148 }
1149
1150 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001151 void addUImmOperands(MCInst &Inst, unsigned N) const {
1152 if (isImm() && !isConstantImm()) {
1153 addExpr(Inst, getImm());
1154 return;
1155 }
1156 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1157 }
1158
Daniel Sanders78e89022016-03-11 11:37:50 +00001159 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1160 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 int64_t Imm = getConstantImm() - Offset;
1163 Imm = SignExtend64<Bits>(Imm);
1164 Imm += Offset;
1165 Imm += AdjustOffset;
1166 Inst.addOperand(MCOperand::createImm(Imm));
1167 }
1168
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001169 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001170 assert(N == 1 && "Invalid number of operands!");
1171 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001173 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001174
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001175 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001176 assert(N == 2 && "Invalid number of operands!");
1177
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001178 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1179 ? getMemBase()->getGPR64Reg()
1180 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001181
1182 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001184 }
1185
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001186 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 2 && "Invalid number of operands!");
1188
Jim Grosbache9119e42015-05-13 18:37:00 +00001189 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001190
1191 const MCExpr *Expr = getMemOff();
1192 addExpr(Inst, Expr);
1193 }
1194
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001195 void addRegListOperands(MCInst &Inst, unsigned N) const {
1196 assert(N == 1 && "Invalid number of operands!");
1197
1198 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001199 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001200 }
1201
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001202 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1203 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001204 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001205 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001206 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1207 Inst.addOperand(MCOperand::createReg(
1208 RegIdx.RegInfo->getRegClass(
1209 AsmParser.getABI().AreGprs64bit()
1210 ? Mips::GPR64RegClassID
1211 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1212 Inst.addOperand(MCOperand::createReg(
1213 RegIdx.RegInfo->getRegClass(
1214 AsmParser.getABI().AreGprs64bit()
1215 ? Mips::GPR64RegClassID
1216 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001217 }
1218
Zoran Jovanovic41688672015-02-10 16:36:20 +00001219 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 2 && "Invalid number of operands!");
1221 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001222 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001223 }
1224
Craig Topper56c590a2014-04-29 07:58:02 +00001225 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001226 // As a special case until we sort out the definition of div/divu, accept
1227 // $0/$zero here so that MCK_ZERO works correctly.
1228 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001230
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001231 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001232 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001233
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001235 int64_t Res;
1236 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001238
Daniel Sanders52da7af2015-11-06 12:11:03 +00001239 bool isConstantImmz() const {
1240 return isConstantImm() && getConstantImm() == 0;
1241 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001242
Daniel Sandersea4f6532015-11-06 12:22:31 +00001243 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1244 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1245 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001246
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001247 template <unsigned Bits> bool isSImm() const {
1248 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1249 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001250
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001251 template <unsigned Bits> bool isUImm() const {
1252 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1253 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001254
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001255 template <unsigned Bits> bool isAnyImm() const {
1256 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1257 isUInt<Bits>(getConstantImm()))
1258 : isImm();
1259 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001260
Daniel Sanders78e89022016-03-11 11:37:50 +00001261 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1262 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001263 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001264
Hrvoje Varga46458d02016-02-25 12:53:29 +00001265 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1266 return isConstantImm() && getConstantImm() >= Bottom &&
1267 getConstantImm() <= Top;
1268 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001269
Craig Topper56c590a2014-04-29 07:58:02 +00001270 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001271 // Note: It's not possible to pretend that other operand kinds are tokens.
1272 // The matcher emitter checks tokens first.
1273 return Kind == k_Token;
1274 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001275
Craig Topper56c590a2014-04-29 07:58:02 +00001276 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001277
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001278 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001279 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001280 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001281
Simon Dardis4ccda502016-05-27 13:56:36 +00001282 // Allow relocation operators.
1283 // FIXME: This predicate and others need to look through binary expressions
1284 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001285 template <unsigned Bits, unsigned ShiftAmount = 0>
1286 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001287 if (!isMem())
1288 return false;
1289 if (!getMemBase()->isGPRAsmReg())
1290 return false;
1291 if (isa<MCTargetExpr>(getMemOff()) ||
1292 (isConstantMemOff() &&
1293 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1294 return true;
1295 MCValue Res;
1296 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1297 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001298 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001299
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001300 bool isMemWithGRPMM16Base() const {
1301 return isMem() && getMemBase()->isMM16AsmReg();
1302 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001303
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001304 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1305 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1306 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1307 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001308
Jozef Kolek12c69822014-12-23 16:16:33 +00001309 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1310 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1311 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1312 && (getMemBase()->getGPR32Reg() == Mips::SP);
1313 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001314
Daniel Sanderse473dc92016-05-09 13:38:25 +00001315 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1316 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1317 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1318 && (getMemBase()->getGPR32Reg() == Mips::GP);
1319 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001320
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001321 template <unsigned Bits, unsigned ShiftLeftAmount>
1322 bool isScaledUImm() const {
1323 return isConstantImm() &&
1324 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001325 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001326
Daniel Sanders97297772016-03-22 14:40:00 +00001327 template <unsigned Bits, unsigned ShiftLeftAmount>
1328 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001329 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1330 return true;
1331 // Operand can also be a symbol or symbol plus offset in case of relocations.
1332 if (Kind != k_Immediate)
1333 return false;
1334 MCValue Res;
1335 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1336 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001337 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001338
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001339 bool isRegList16() const {
1340 if (!isRegList())
1341 return false;
1342
1343 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001344 if (Size < 2 || Size > 5)
1345 return false;
1346
1347 unsigned R0 = RegList.List->front();
1348 unsigned R1 = RegList.List->back();
1349 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1350 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001351 return false;
1352
1353 int PrevReg = *RegList.List->begin();
1354 for (int i = 1; i < Size - 1; i++) {
1355 int Reg = (*(RegList.List))[i];
1356 if ( Reg != PrevReg + 1)
1357 return false;
1358 PrevReg = Reg;
1359 }
1360
1361 return true;
1362 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001363
Vladimir Medic2b953d02013-10-01 09:48:56 +00001364 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001365
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001366 bool isLSAImm() const {
1367 if (!isConstantImm())
1368 return false;
1369 int64_t Val = getConstantImm();
1370 return 1 <= Val && Val <= 4;
1371 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001372
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001373 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001374
Zoran Jovanovic41688672015-02-10 16:36:20 +00001375 bool isMovePRegPair() const {
1376 if (Kind != k_RegList || RegList.List->size() != 2)
1377 return false;
1378
1379 unsigned R0 = RegList.List->front();
1380 unsigned R1 = RegList.List->back();
1381
1382 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1383 (R0 == Mips::A1 && R1 == Mips::A3) ||
1384 (R0 == Mips::A2 && R1 == Mips::A3) ||
1385 (R0 == Mips::A0 && R1 == Mips::S5) ||
1386 (R0 == Mips::A0 && R1 == Mips::S6) ||
1387 (R0 == Mips::A0 && R1 == Mips::A1) ||
1388 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001389 (R0 == Mips::A0 && R1 == Mips::A3) ||
1390 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1391 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1392 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1393 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1394 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1395 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1396 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1397 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001398 return true;
1399
1400 return false;
1401 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001402
1403 StringRef getToken() const {
1404 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001405 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001406 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001407
Zlatko Buljanba553a62016-05-09 08:07:28 +00001408 bool isRegPair() const {
1409 return Kind == k_RegPair && RegIdx.Index <= 30;
1410 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001411
Craig Topper56c590a2014-04-29 07:58:02 +00001412 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001413 // As a special case until we sort out the definition of div/divu, accept
1414 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1416 RegIdx.Kind & RegKind_GPR)
1417 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001418
Daniel Sanders976d9382016-07-05 13:38:40 +00001419 llvm_unreachable("Invalid access!");
1420 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001421 }
1422
Jack Carterb4dbc172012-09-05 23:34:03 +00001423 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001424 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001425 return Imm.Val;
1426 }
1427
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001428 int64_t getConstantImm() const {
1429 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001430 int64_t Value = 0;
1431 (void)Val->evaluateAsAbsolute(Value);
1432 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001433 }
1434
1435 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001436 assert((Kind == k_Memory) && "Invalid access!");
1437 return Mem.Base;
1438 }
1439
1440 const MCExpr *getMemOff() const {
1441 assert((Kind == k_Memory) && "Invalid access!");
1442 return Mem.Off;
1443 }
1444
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001445 int64_t getConstantMemOff() const {
1446 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1447 }
1448
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001449 const SmallVectorImpl<unsigned> &getRegList() const {
1450 assert((Kind == k_RegList) && "Invalid access!");
1451 return *(RegList.List);
1452 }
1453
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001454 unsigned getRegPair() const {
1455 assert((Kind == k_RegPair) && "Invalid access!");
1456 return RegIdx.Index;
1457 }
1458
David Blaikie960ea3f2014-06-08 16:18:35 +00001459 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1460 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001461 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001462 Op->Tok.Data = Str.data();
1463 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001464 Op->StartLoc = S;
1465 Op->EndLoc = S;
1466 return Op;
1467 }
1468
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001469 /// Create a numeric register (e.g. $1). The exact register remains
1470 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001471 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001472 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1473 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001474 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001475 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001476 }
1477
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001478 /// Create a register that is definitely a GPR.
1479 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001480 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001481 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1482 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1483 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001484 }
1485
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001486 /// Create a register that is definitely a FGR.
1487 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001488 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001489 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1490 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1491 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001492 }
1493
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001494 /// Create a register that is definitely a HWReg.
1495 /// This is typically only used for named registers such as $hwr_cpunum.
1496 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001497 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001498 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001499 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001500 }
1501
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001502 /// Create a register that is definitely an FCC.
1503 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001504 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001505 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1506 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1507 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001508 }
1509
1510 /// Create a register that is definitely an ACC.
1511 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001512 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001513 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1514 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1515 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001516 }
1517
1518 /// Create a register that is definitely an MSA128.
1519 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001520 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001521 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1522 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1523 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001524 }
1525
1526 /// Create a register that is definitely an MSACtrl.
1527 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001528 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001529 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1530 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1531 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001532 }
1533
David Blaikie960ea3f2014-06-08 16:18:35 +00001534 static std::unique_ptr<MipsOperand>
1535 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001536 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001537 Op->Imm.Val = Val;
1538 Op->StartLoc = S;
1539 Op->EndLoc = E;
1540 return Op;
1541 }
1542
David Blaikie960ea3f2014-06-08 16:18:35 +00001543 static std::unique_ptr<MipsOperand>
1544 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1545 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001546 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001547 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001548 Op->Mem.Off = Off;
1549 Op->StartLoc = S;
1550 Op->EndLoc = E;
1551 return Op;
1552 }
1553
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001554 static std::unique_ptr<MipsOperand>
1555 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1556 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001557 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001558
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001559 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001560 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001561 Op->StartLoc = StartLoc;
1562 Op->EndLoc = EndLoc;
1563 return Op;
1564 }
1565
Daniel Sandersd044e492016-05-09 13:10:57 +00001566 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1567 SMLoc S, SMLoc E,
1568 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001569 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001570 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001571 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1572 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001573 Op->StartLoc = S;
1574 Op->EndLoc = E;
1575 return Op;
1576 }
1577
Simon Dardis509da1a2017-02-13 16:06:48 +00001578 bool isGPRZeroAsmReg() const {
1579 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1580 }
1581
1582 bool isGPRNonZeroAsmReg() const {
1583 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1584 RegIdx.Index <= 31;
1585 }
1586
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001587 bool isGPRAsmReg() const {
1588 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001590
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001591 bool isMM16AsmReg() const {
1592 if (!(isRegIdx() && RegIdx.Kind))
1593 return false;
1594 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1595 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001596
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001597 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001598 bool isMM16AsmRegZero() const {
1599 if (!(isRegIdx() && RegIdx.Kind))
1600 return false;
1601 return (RegIdx.Index == 0 ||
1602 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1603 RegIdx.Index == 17);
1604 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001605
Zoran Jovanovic41688672015-02-10 16:36:20 +00001606 bool isMM16AsmRegMoveP() const {
1607 if (!(isRegIdx() && RegIdx.Kind))
1608 return false;
1609 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1610 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1611 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001613 bool isFGRAsmReg() const {
1614 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1615 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001616 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001617
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001618 bool isStrictlyFGRAsmReg() const {
1619 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1620 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1621 }
1622
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001623 bool isHWRegsAsmReg() const {
1624 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001626
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001627 bool isCCRAsmReg() const {
1628 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001632 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1633 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001634 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001635 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001636
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001637 bool isACCAsmReg() const {
1638 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001639 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001640
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001641 bool isCOP0AsmReg() const {
1642 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1643 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001644
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001645 bool isCOP2AsmReg() const {
1646 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001647 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001648
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001649 bool isCOP3AsmReg() const {
1650 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1651 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001652
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 bool isMSA128AsmReg() const {
1654 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001655 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001656
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001657 bool isMSACtrlAsmReg() const {
1658 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001659 }
1660
Jack Carterb4dbc172012-09-05 23:34:03 +00001661 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001662 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001663 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001664 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001665
Craig Topper56c590a2014-04-29 07:58:02 +00001666 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001667 switch (Kind) {
1668 case k_Immediate:
1669 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001670 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001671 OS << ">";
1672 break;
1673 case k_Memory:
1674 OS << "Mem<";
1675 Mem.Base->print(OS);
1676 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001677 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001678 OS << ">";
1679 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001680 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001681 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1682 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001683 break;
1684 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001685 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001686 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001687 case k_RegList:
1688 OS << "RegList< ";
1689 for (auto Reg : (*RegList.List))
1690 OS << Reg << " ";
1691 OS << ">";
1692 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001693 case k_RegPair:
1694 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1695 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001696 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001697 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001698
1699 bool isValidForTie(const MipsOperand &Other) const {
1700 if (Kind != Other.Kind)
1701 return false;
1702
1703 switch (Kind) {
1704 default:
1705 llvm_unreachable("Unexpected kind");
1706 return false;
1707 case k_RegisterIndex: {
1708 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1709 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1710 return Token == OtherToken;
1711 }
1712 }
1713 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001714}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001715
1716} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001717
Jack Carter9e65aa32013-03-22 00:05:30 +00001718namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001719
Jack Carter9e65aa32013-03-22 00:05:30 +00001720extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001721
1722} // end namespace llvm
1723
Jack Carter9e65aa32013-03-22 00:05:30 +00001724static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1725 return MipsInsts[Opcode];
1726}
1727
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001728static bool hasShortDelaySlot(unsigned Opcode) {
1729 switch (Opcode) {
1730 case Mips::JALS_MM:
1731 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001732 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001733 case Mips::BGEZALS_MM:
1734 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001735 return true;
1736 default:
1737 return false;
1738 }
1739}
1740
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001741static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1742 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1743 return &SRExpr->getSymbol();
1744 }
1745
1746 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1747 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1748 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1749
1750 if (LHSSym)
1751 return LHSSym;
1752
1753 if (RHSSym)
1754 return RHSSym;
1755
1756 return nullptr;
1757 }
1758
1759 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1760 return getSingleMCSymbol(UExpr->getSubExpr());
1761
1762 return nullptr;
1763}
1764
1765static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1766 if (isa<MCSymbolRefExpr>(Expr))
1767 return 1;
1768
1769 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1770 return countMCSymbolRefExpr(BExpr->getLHS()) +
1771 countMCSymbolRefExpr(BExpr->getRHS());
1772
1773 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1774 return countMCSymbolRefExpr(UExpr->getSubExpr());
1775
1776 return 0;
1777}
1778
Jack Carter9e65aa32013-03-22 00:05:30 +00001779bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001780 MCStreamer &Out,
1781 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001782 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001783 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001784 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001785
Jack Carter9e65aa32013-03-22 00:05:30 +00001786 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001787
1788 if (MCID.isBranch() || MCID.isCall()) {
1789 const unsigned Opcode = Inst.getOpcode();
1790 MCOperand Offset;
1791
1792 switch (Opcode) {
1793 default:
1794 break;
Kai Nackee0245392015-01-27 19:11:28 +00001795 case Mips::BBIT0:
1796 case Mips::BBIT032:
1797 case Mips::BBIT1:
1798 case Mips::BBIT132:
1799 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001800 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001801
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001802 case Mips::BEQ:
1803 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804 case Mips::BEQ_MM:
1805 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001806 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001807 Offset = Inst.getOperand(2);
1808 if (!Offset.isImm())
1809 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001810 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001811 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001812 if (OffsetToAlignment(Offset.getImm(),
1813 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001814 return Error(IDLoc, "branch to misaligned address");
1815 break;
1816 case Mips::BGEZ:
1817 case Mips::BGTZ:
1818 case Mips::BLEZ:
1819 case Mips::BLTZ:
1820 case Mips::BGEZAL:
1821 case Mips::BLTZAL:
1822 case Mips::BC1F:
1823 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001824 case Mips::BGEZ_MM:
1825 case Mips::BGTZ_MM:
1826 case Mips::BLEZ_MM:
1827 case Mips::BLTZ_MM:
1828 case Mips::BGEZAL_MM:
1829 case Mips::BLTZAL_MM:
1830 case Mips::BC1F_MM:
1831 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001832 case Mips::BC1EQZC_MMR6:
1833 case Mips::BC1NEZC_MMR6:
1834 case Mips::BC2EQZC_MMR6:
1835 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001836 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001837 Offset = Inst.getOperand(1);
1838 if (!Offset.isImm())
1839 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001840 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001841 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001842 if (OffsetToAlignment(Offset.getImm(),
1843 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001844 return Error(IDLoc, "branch to misaligned address");
1845 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001846 case Mips::BGEC: case Mips::BGEC_MMR6:
1847 case Mips::BLTC: case Mips::BLTC_MMR6:
1848 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1849 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1850 case Mips::BEQC: case Mips::BEQC_MMR6:
1851 case Mips::BNEC: case Mips::BNEC_MMR6:
1852 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1853 Offset = Inst.getOperand(2);
1854 if (!Offset.isImm())
1855 break; // We'll deal with this situation later on when applying fixups.
1856 if (!isIntN(18, Offset.getImm()))
1857 return Error(IDLoc, "branch target out of range");
1858 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1859 return Error(IDLoc, "branch to misaligned address");
1860 break;
1861 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1862 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1863 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1864 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1865 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1866 Offset = Inst.getOperand(1);
1867 if (!Offset.isImm())
1868 break; // We'll deal with this situation later on when applying fixups.
1869 if (!isIntN(18, Offset.getImm()))
1870 return Error(IDLoc, "branch target out of range");
1871 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1872 return Error(IDLoc, "branch to misaligned address");
1873 break;
1874 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1875 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1876 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1877 Offset = Inst.getOperand(1);
1878 if (!Offset.isImm())
1879 break; // We'll deal with this situation later on when applying fixups.
1880 if (!isIntN(23, Offset.getImm()))
1881 return Error(IDLoc, "branch target out of range");
1882 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1883 return Error(IDLoc, "branch to misaligned address");
1884 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001885 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001886 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001887 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001888 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001889 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1890 Offset = Inst.getOperand(1);
1891 if (!Offset.isImm())
1892 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001893 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001894 return Error(IDLoc, "branch target out of range");
1895 if (OffsetToAlignment(Offset.getImm(), 2LL))
1896 return Error(IDLoc, "branch to misaligned address");
1897 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001898 }
1899 }
1900
Daniel Sandersa84989a2014-06-16 13:25:35 +00001901 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1902 // We still accept it but it is a normal nop.
1903 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1904 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1905 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1906 "nop instruction");
1907 }
1908
Kai Nackee0245392015-01-27 19:11:28 +00001909 if (hasCnMips()) {
1910 const unsigned Opcode = Inst.getOpcode();
1911 MCOperand Opnd;
1912 int Imm;
1913
1914 switch (Opcode) {
1915 default:
1916 break;
1917
1918 case Mips::BBIT0:
1919 case Mips::BBIT032:
1920 case Mips::BBIT1:
1921 case Mips::BBIT132:
1922 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1923 // The offset is handled above
1924 Opnd = Inst.getOperand(1);
1925 if (!Opnd.isImm())
1926 return Error(IDLoc, "expected immediate operand kind");
1927 Imm = Opnd.getImm();
1928 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1929 Opcode == Mips::BBIT1 ? 63 : 31))
1930 return Error(IDLoc, "immediate operand value out of range");
1931 if (Imm > 31) {
1932 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1933 : Mips::BBIT132);
1934 Inst.getOperand(1).setImm(Imm - 32);
1935 }
1936 break;
1937
Kai Nackee0245392015-01-27 19:11:28 +00001938 case Mips::SEQi:
1939 case Mips::SNEi:
1940 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1941 Opnd = Inst.getOperand(2);
1942 if (!Opnd.isImm())
1943 return Error(IDLoc, "expected immediate operand kind");
1944 Imm = Opnd.getImm();
1945 if (!isInt<10>(Imm))
1946 return Error(IDLoc, "immediate operand value out of range");
1947 break;
1948 }
1949 }
1950
Simon Dardis509da1a2017-02-13 16:06:48 +00001951 // Warn on division by zero. We're checking here as all instructions get
1952 // processed here, not just the macros that need expansion.
1953 //
1954 // The MIPS backend models most of the divison instructions and macros as
1955 // three operand instructions. The pre-R6 divide instructions however have
1956 // two operands and explicitly define HI/LO as part of the instruction,
1957 // not in the operands.
1958 unsigned FirstOp = 1;
1959 unsigned SecondOp = 2;
1960 switch (Inst.getOpcode()) {
1961 default:
1962 break;
1963 case Mips::SDivIMacro:
1964 case Mips::UDivIMacro:
1965 case Mips::DSDivIMacro:
1966 case Mips::DUDivIMacro:
1967 if (Inst.getOperand(2).getImm() == 0) {
1968 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1969 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1970 Warning(IDLoc, "dividing zero by zero");
1971 else
1972 Warning(IDLoc, "division by zero");
1973 }
1974 break;
1975 case Mips::DSDIV:
1976 case Mips::SDIV:
1977 case Mips::UDIV:
1978 case Mips::DUDIV:
1979 case Mips::UDIV_MM:
1980 case Mips::SDIV_MM:
1981 FirstOp = 0;
1982 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001983 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001984 case Mips::SDivMacro:
1985 case Mips::DSDivMacro:
1986 case Mips::UDivMacro:
1987 case Mips::DUDivMacro:
1988 case Mips::DIV:
1989 case Mips::DIVU:
1990 case Mips::DDIV:
1991 case Mips::DDIVU:
1992 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001993 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001994 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1995 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1996 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1997 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1998 Warning(IDLoc, "dividing zero by zero");
1999 else
2000 Warning(IDLoc, "division by zero");
2001 }
2002 break;
2003 }
2004
Simon Atanasyan50485142016-12-12 17:40:26 +00002005 // For PIC code convert unconditional jump to unconditional branch.
2006 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2007 inPicMode()) {
2008 MCInst BInst;
2009 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2010 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2011 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2012 BInst.addOperand(Inst.getOperand(0));
2013 Inst = BInst;
2014 }
2015
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002016 // This expansion is not in a function called by tryExpandInstruction()
2017 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002018 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2019 inPicMode()) {
2020 warnIfNoMacro(IDLoc);
2021
2022 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2023
2024 // We can do this expansion if there's only 1 symbol in the argument
2025 // expression.
2026 if (countMCSymbolRefExpr(JalExpr) > 1)
2027 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2028
2029 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002030 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002031 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2032
2033 // FIXME: Add support for label+offset operands (currently causes an error).
2034 // FIXME: Add support for forward-declared local symbols.
2035 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002036 if (JalSym->isInSection() || JalSym->isTemporary() ||
2037 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002038 if (isABI_O32()) {
2039 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002040 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002041 // R_(MICRO)MIPS_GOT16 label
2042 // addiu $25, $25, 0
2043 // R_(MICRO)MIPS_LO16 label
2044 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002045 const MCExpr *Got16RelocExpr =
2046 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2047 const MCExpr *Lo16RelocExpr =
2048 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002049
Daniel Sandersa736b372016-04-29 13:33:12 +00002050 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2051 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2052 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2053 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002054 } else if (isABI_N32() || isABI_N64()) {
2055 // If it's a local symbol and the N32/N64 ABIs are being used,
2056 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002057 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002058 // R_(MICRO)MIPS_GOT_DISP label
2059 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002060 const MCExpr *GotDispRelocExpr =
2061 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002062
Daniel Sandersa736b372016-04-29 13:33:12 +00002063 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2064 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2065 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002066 }
2067 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002068 // If it's an external/weak symbol, we expand to:
2069 // lw/ld $25, 0($gp)
2070 // R_(MICRO)MIPS_CALL16 label
2071 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002072 const MCExpr *Call16RelocExpr =
2073 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002074
Daniel Sandersa736b372016-04-29 13:33:12 +00002075 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2076 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002077 }
2078
2079 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002080 if (IsCpRestoreSet && inMicroMipsMode())
2081 JalrInst.setOpcode(Mips::JALRS_MM);
2082 else
2083 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002084 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2085 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2086
2087 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2088 // This relocation is supposed to be an optimization hint for the linker
2089 // and is not necessary for correctness.
2090
2091 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002092 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002093 }
2094
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002095 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2096 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002097 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 // reference or immediate we may have to expand instructions.
2099 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002100 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002101 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2102 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002103 MCOperand &Op = Inst.getOperand(i);
2104 if (Op.isImm()) {
2105 int MemOffset = Op.getImm();
2106 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002108 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002109 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002110 }
2111 } else if (Op.isExpr()) {
2112 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002114 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002115 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002116 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002117 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002118 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002119 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002120 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002121 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002122 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002123 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002124 }
2125 }
2126 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002127 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002128 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002129
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002130 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002131 if (MCID.mayLoad()) {
2132 // Try to create 16-bit GP relative load instruction.
2133 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2134 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2135 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2136 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2137 MCOperand &Op = Inst.getOperand(i);
2138 if (Op.isImm()) {
2139 int MemOffset = Op.getImm();
2140 MCOperand &DstReg = Inst.getOperand(0);
2141 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002142 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002143 getContext().getRegisterInfo()->getRegClass(
2144 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002145 (BaseReg.getReg() == Mips::GP ||
2146 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002147
Daniel Sandersa736b372016-04-29 13:33:12 +00002148 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2149 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002150 return false;
2151 }
2152 }
2153 }
2154 } // for
2155 } // if load
2156
2157 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2158
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002159 MCOperand Opnd;
2160 int Imm;
2161
2162 switch (Inst.getOpcode()) {
2163 default:
2164 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002165 case Mips::ADDIUSP_MM:
2166 Opnd = Inst.getOperand(0);
2167 if (!Opnd.isImm())
2168 return Error(IDLoc, "expected immediate operand kind");
2169 Imm = Opnd.getImm();
2170 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2171 Imm % 4 != 0)
2172 return Error(IDLoc, "immediate operand value out of range");
2173 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002174 case Mips::SLL16_MM:
2175 case Mips::SRL16_MM:
2176 Opnd = Inst.getOperand(2);
2177 if (!Opnd.isImm())
2178 return Error(IDLoc, "expected immediate operand kind");
2179 Imm = Opnd.getImm();
2180 if (Imm < 1 || Imm > 8)
2181 return Error(IDLoc, "immediate operand value out of range");
2182 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002183 case Mips::LI16_MM:
2184 Opnd = Inst.getOperand(1);
2185 if (!Opnd.isImm())
2186 return Error(IDLoc, "expected immediate operand kind");
2187 Imm = Opnd.getImm();
2188 if (Imm < -1 || Imm > 126)
2189 return Error(IDLoc, "immediate operand value out of range");
2190 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002191 case Mips::ADDIUR2_MM:
2192 Opnd = Inst.getOperand(2);
2193 if (!Opnd.isImm())
2194 return Error(IDLoc, "expected immediate operand kind");
2195 Imm = Opnd.getImm();
2196 if (!(Imm == 1 || Imm == -1 ||
2197 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2198 return Error(IDLoc, "immediate operand value out of range");
2199 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002200 case Mips::ANDI16_MM:
2201 Opnd = Inst.getOperand(2);
2202 if (!Opnd.isImm())
2203 return Error(IDLoc, "expected immediate operand kind");
2204 Imm = Opnd.getImm();
2205 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2206 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2207 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2208 return Error(IDLoc, "immediate operand value out of range");
2209 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002210 case Mips::LBU16_MM:
2211 Opnd = Inst.getOperand(2);
2212 if (!Opnd.isImm())
2213 return Error(IDLoc, "expected immediate operand kind");
2214 Imm = Opnd.getImm();
2215 if (Imm < -1 || Imm > 14)
2216 return Error(IDLoc, "immediate operand value out of range");
2217 break;
2218 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002219 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002220 Opnd = Inst.getOperand(2);
2221 if (!Opnd.isImm())
2222 return Error(IDLoc, "expected immediate operand kind");
2223 Imm = Opnd.getImm();
2224 if (Imm < 0 || Imm > 15)
2225 return Error(IDLoc, "immediate operand value out of range");
2226 break;
2227 case Mips::LHU16_MM:
2228 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002229 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002230 Opnd = Inst.getOperand(2);
2231 if (!Opnd.isImm())
2232 return Error(IDLoc, "expected immediate operand kind");
2233 Imm = Opnd.getImm();
2234 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2235 return Error(IDLoc, "immediate operand value out of range");
2236 break;
2237 case Mips::LW16_MM:
2238 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002239 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002240 Opnd = Inst.getOperand(2);
2241 if (!Opnd.isImm())
2242 return Error(IDLoc, "expected immediate operand kind");
2243 Imm = Opnd.getImm();
2244 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2245 return Error(IDLoc, "immediate operand value out of range");
2246 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002247 case Mips::ADDIUPC_MM:
2248 MCOperand Opnd = Inst.getOperand(1);
2249 if (!Opnd.isImm())
2250 return Error(IDLoc, "expected immediate operand kind");
2251 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002252 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002253 return Error(IDLoc, "immediate operand value out of range");
2254 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002255 }
2256 }
2257
Daniel Sandersd8c07762016-04-18 12:35:36 +00002258 bool FillDelaySlot =
2259 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2260 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002261 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002262
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002263 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002264 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002265 switch (ExpandResult) {
2266 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002267 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002268 break;
2269 case MER_Success:
2270 break;
2271 case MER_Fail:
2272 return true;
2273 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002274
Daniel Sanderscda908a2016-05-16 09:10:13 +00002275 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2276 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002277 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002278 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002279 TOut.updateABIInfo(*this);
2280 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002281
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002282 // If this instruction has a delay slot and .set reorder is active,
2283 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002284 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002285 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2286 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002287 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002288
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002289 if ((Inst.getOpcode() == Mips::JalOneReg ||
2290 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2291 isPicAndNotNxxAbi()) {
2292 if (IsCpRestoreSet) {
2293 // We need a NOP between the JALR and the LW:
2294 // If .set reorder has been used, we've already emitted a NOP.
2295 // If .set noreorder has been used, we need to emit a NOP at this point.
2296 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002297 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2298 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002299
2300 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002301 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002302 } else
2303 Warning(IDLoc, "no .cprestore used in PIC mode");
2304 }
2305
Jack Carter9e65aa32013-03-22 00:05:30 +00002306 return false;
2307}
2308
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002309MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002310MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2311 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002312 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002313 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002314 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002315 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002316 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002317 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002318 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002319 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002320 case Mips::LoadAddrImm64:
2321 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2322 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2323 "expected immediate operand kind");
2324
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002325 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2326 Inst.getOperand(1),
2327 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002328 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002329 ? MER_Fail
2330 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002331 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002332 case Mips::LoadAddrReg64:
2333 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2334 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2335 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2336 "expected immediate operand kind");
2337
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002338 return expandLoadAddress(Inst.getOperand(0).getReg(),
2339 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2340 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002341 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002342 ? MER_Fail
2343 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002344 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002345 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002346 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2347 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002348 case Mips::SWM_MM:
2349 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002350 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2351 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002352 case Mips::JalOneReg:
2353 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002354 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002355 case Mips::BneImm:
2356 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002357 case Mips::BEQLImmMacro:
2358 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002359 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002360 case Mips::BLT:
2361 case Mips::BLE:
2362 case Mips::BGE:
2363 case Mips::BGT:
2364 case Mips::BLTU:
2365 case Mips::BLEU:
2366 case Mips::BGEU:
2367 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002368 case Mips::BLTL:
2369 case Mips::BLEL:
2370 case Mips::BGEL:
2371 case Mips::BGTL:
2372 case Mips::BLTUL:
2373 case Mips::BLEUL:
2374 case Mips::BGEUL:
2375 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002376 case Mips::BLTImmMacro:
2377 case Mips::BLEImmMacro:
2378 case Mips::BGEImmMacro:
2379 case Mips::BGTImmMacro:
2380 case Mips::BLTUImmMacro:
2381 case Mips::BLEUImmMacro:
2382 case Mips::BGEUImmMacro:
2383 case Mips::BGTUImmMacro:
2384 case Mips::BLTLImmMacro:
2385 case Mips::BLELImmMacro:
2386 case Mips::BGELImmMacro:
2387 case Mips::BGTLImmMacro:
2388 case Mips::BLTULImmMacro:
2389 case Mips::BLEULImmMacro:
2390 case Mips::BGEULImmMacro:
2391 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002392 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002393 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002394 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002395 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2396 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002397 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002398 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002399 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2400 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002401 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002402 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002403 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2404 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002405 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002406 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002407 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2408 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002409 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002410 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2411 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002412 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002413 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002414 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002415 case Mips::PseudoTRUNC_W_D:
2416 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2417 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002418
2419 case Mips::LoadImmSingleGPR:
2420 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2421 ? MER_Fail
2422 : MER_Success;
2423 case Mips::LoadImmSingleFGR:
2424 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2425 ? MER_Fail
2426 : MER_Success;
2427 case Mips::LoadImmDoubleGPR:
2428 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2429 ? MER_Fail
2430 : MER_Success;
2431 case Mips::LoadImmDoubleFGR:
2432 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2433 ? MER_Fail
2434 : MER_Success;
2435 case Mips::LoadImmDoubleFGR_32:
2436 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2437 ? MER_Fail
2438 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002439 case Mips::Ulh:
2440 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2441 case Mips::Ulhu:
2442 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002443 case Mips::Ush:
2444 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002445 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002446 case Mips::Usw:
2447 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002448 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002449 case Mips::NORImm64:
2450 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2451 case Mips::SLTImm64:
2452 if (isInt<16>(Inst.getOperand(2).getImm())) {
2453 Inst.setOpcode(Mips::SLTi64);
2454 return MER_NotAMacro;
2455 }
2456 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2457 case Mips::SLTUImm64:
2458 if (isInt<16>(Inst.getOperand(2).getImm())) {
2459 Inst.setOpcode(Mips::SLTiu64);
2460 return MER_NotAMacro;
2461 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002462 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002463 case Mips::ADDi: case Mips::ADDi_MM:
2464 case Mips::ADDiu: case Mips::ADDiu_MM:
2465 case Mips::SLTi: case Mips::SLTi_MM:
2466 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002467 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2468 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2469 int64_t ImmValue = Inst.getOperand(2).getImm();
2470 if (isInt<16>(ImmValue))
2471 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002472 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2473 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002474 }
2475 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002476 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2477 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2478 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002479 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2480 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2481 int64_t ImmValue = Inst.getOperand(2).getImm();
2482 if (isUInt<16>(ImmValue))
2483 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002484 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2485 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002486 }
2487 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002488 case Mips::ROL:
2489 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002490 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002491 case Mips::ROLImm:
2492 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002493 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002494 case Mips::DROL:
2495 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002496 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002497 case Mips::DROLImm:
2498 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002499 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002500 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002501 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002502 case Mips::MULImmMacro:
2503 case Mips::DMULImmMacro:
2504 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2505 case Mips::MULOMacro:
2506 case Mips::DMULOMacro:
2507 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2508 case Mips::MULOUMacro:
2509 case Mips::DMULOUMacro:
2510 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2511 case Mips::DMULMacro:
2512 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002513 case Mips::LDMacro:
2514 case Mips::SDMacro:
2515 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2516 Inst.getOpcode() == Mips::LDMacro)
2517 ? MER_Fail
2518 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002519 case Mips::SEQMacro:
2520 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2521 case Mips::SEQIMacro:
2522 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002523 case Mips::MFTC0: case Mips::MTTC0:
2524 case Mips::MFTGPR: case Mips::MTTGPR:
2525 case Mips::MFTLO: case Mips::MTTLO:
2526 case Mips::MFTHI: case Mips::MTTHI:
2527 case Mips::MFTACX: case Mips::MTTACX:
2528 case Mips::MFTDSP: case Mips::MTTDSP:
2529 case Mips::MFTC1: case Mips::MTTC1:
2530 case Mips::MFTHC1: case Mips::MTTHC1:
2531 case Mips::CFTC1: case Mips::CTTC1:
2532 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 }
Jack Carter30a59822012-10-04 04:03:53 +00002534}
Jack Carter92995f12012-10-06 00:53:28 +00002535
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002536bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002537 MCStreamer &Out,
2538 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002539 MipsTargetStreamer &TOut = getTargetStreamer();
2540
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002541 // Create a JALR instruction which is going to replace the pseudo-JAL.
2542 MCInst JalrInst;
2543 JalrInst.setLoc(IDLoc);
2544 const MCOperand FirstRegOp = Inst.getOperand(0);
2545 const unsigned Opcode = Inst.getOpcode();
2546
2547 if (Opcode == Mips::JalOneReg) {
2548 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002549 if (IsCpRestoreSet && inMicroMipsMode()) {
2550 JalrInst.setOpcode(Mips::JALRS16_MM);
2551 JalrInst.addOperand(FirstRegOp);
2552 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002553 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002554 JalrInst.addOperand(FirstRegOp);
2555 } else {
2556 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002557 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002558 JalrInst.addOperand(FirstRegOp);
2559 }
2560 } else if (Opcode == Mips::JalTwoReg) {
2561 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002562 if (IsCpRestoreSet && inMicroMipsMode())
2563 JalrInst.setOpcode(Mips::JALRS_MM);
2564 else
2565 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002566 JalrInst.addOperand(FirstRegOp);
2567 const MCOperand SecondRegOp = Inst.getOperand(1);
2568 JalrInst.addOperand(SecondRegOp);
2569 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002570 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002571
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002572 // If .set reorder is active and branch instruction has a delay slot,
2573 // emit a NOP after it.
2574 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002575 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2576 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2577 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002578
2579 return false;
2580}
2581
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002582/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002583template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002584 unsigned BitNum = findFirstSet(x);
2585
2586 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2587}
2588
2589/// Load (or add) an immediate into a register.
2590///
2591/// @param ImmValue The immediate to load.
2592/// @param DstReg The register that will hold the immediate.
2593/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2594/// for a simple initialization.
2595/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2596/// @param IsAddress True if the immediate represents an address. False if it
2597/// is an integer.
2598/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002599bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002600 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002601 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2602 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002603 MipsTargetStreamer &TOut = getTargetStreamer();
2604
Toma Tabacu00e98672015-05-01 12:19:27 +00002605 if (!Is32BitImm && !isGP64bit()) {
2606 Error(IDLoc, "instruction requires a 64-bit architecture");
2607 return true;
2608 }
2609
Daniel Sanders03f9c012015-07-14 12:24:22 +00002610 if (Is32BitImm) {
2611 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2612 // Sign extend up to 64-bit so that the predicates match the hardware
2613 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2614 // true.
2615 ImmValue = SignExtend64<32>(ImmValue);
2616 } else {
2617 Error(IDLoc, "instruction requires a 32-bit immediate");
2618 return true;
2619 }
2620 }
2621
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002622 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2623 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2624
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002625 bool UseSrcReg = false;
2626 if (SrcReg != Mips::NoRegister)
2627 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002628
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002629 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002630 if (UseSrcReg &&
2631 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002632 // At this point we need AT to perform the expansions and we exit if it is
2633 // not available.
2634 unsigned ATReg = getATReg(IDLoc);
2635 if (!ATReg)
2636 return true;
2637 TmpReg = ATReg;
2638 }
2639
Daniel Sanders03f9c012015-07-14 12:24:22 +00002640 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002641 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002642 SrcReg = ZeroReg;
2643
2644 // This doesn't quite follow the usual ABI expectations for N32 but matches
2645 // traditional assembler behaviour. N32 would normally use addiu for both
2646 // integers and addresses.
2647 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002648 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002649 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002650 }
2651
Daniel Sandersa736b372016-04-29 13:33:12 +00002652 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002653 return false;
2654 }
2655
2656 if (isUInt<16>(ImmValue)) {
2657 unsigned TmpReg = DstReg;
2658 if (SrcReg == DstReg) {
2659 TmpReg = getATReg(IDLoc);
2660 if (!TmpReg)
2661 return true;
2662 }
2663
Daniel Sandersa736b372016-04-29 13:33:12 +00002664 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002665 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002666 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002667 return false;
2668 }
2669
2670 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002671 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002672
Toma Tabacu79588102015-04-29 10:19:56 +00002673 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2674 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002675 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002676 // Traditional behaviour seems to special case this particular value. It's
2677 // not clear why other masks are handled differently.
2678 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002679 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2680 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002681 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002682 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002683 return false;
2684 }
2685
2686 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002687 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002688 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2689 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002690 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002691 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002692 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002693 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002694 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002695 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002696
Daniel Sandersa736b372016-04-29 13:33:12 +00002697 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002698 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002699 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002700 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002701 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002702 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002703 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002704
2705 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2706 if (Is32BitImm) {
2707 Error(IDLoc, "instruction requires a 32-bit immediate");
2708 return true;
2709 }
2710
2711 // Traditionally, these immediates are shifted as little as possible and as
2712 // such we align the most significant bit to bit 15 of our temporary.
2713 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2714 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2715 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2716 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002717 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2718 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002719
2720 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002721 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002722
2723 return false;
2724 }
2725
2726 warnIfNoMacro(IDLoc);
2727
2728 // The remaining case is packed with a sequence of dsll and ori with zeros
2729 // being omitted and any neighbouring dsll's being coalesced.
2730 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2731
2732 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2733 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002734 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002735 return false;
2736
2737 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2738 // skip it and defer the shift to the next chunk.
2739 unsigned ShiftCarriedForwards = 16;
2740 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2741 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2742
2743 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002744 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2745 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002746 ShiftCarriedForwards = 0;
2747 }
2748
2749 ShiftCarriedForwards += 16;
2750 }
2751 ShiftCarriedForwards -= 16;
2752
2753 // Finish any remaining shifts left by trailing zeros.
2754 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002755 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002756
2757 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002758 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002759
Matheus Almeida3813d572014-06-19 14:39:14 +00002760 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002761}
Jack Carter92995f12012-10-06 00:53:28 +00002762
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002763bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002764 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002765 const MCOperand &ImmOp = Inst.getOperand(1);
2766 assert(ImmOp.isImm() && "expected immediate operand kind");
2767 const MCOperand &DstRegOp = Inst.getOperand(0);
2768 assert(DstRegOp.isReg() && "expected register operand kind");
2769
2770 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002771 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002772 return true;
2773
2774 return false;
2775}
2776
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002777bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2778 const MCOperand &Offset,
2779 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002780 MCStreamer &Out,
2781 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002782 // la can't produce a usable address when addresses are 64-bit.
2783 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2784 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2785 // We currently can't do this because we depend on the equality
2786 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2787 Error(IDLoc, "la used to load 64-bit address");
2788 // Continue as if we had 'dla' instead.
2789 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002790 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002791 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002792
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002793 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002794 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002795 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002796 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002797 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002798
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002799 if (!Offset.isImm())
2800 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002801 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002802
Scott Egerton24557012016-01-21 15:11:01 +00002803 if (!ABI.ArePtrs64bit()) {
2804 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2805 Is32BitAddress = true;
2806 }
2807
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002808 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002809 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002810}
2811
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002812bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2813 unsigned DstReg, unsigned SrcReg,
2814 bool Is32BitSym, SMLoc IDLoc,
2815 MCStreamer &Out,
2816 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002817 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002818 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002819 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002820 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002821
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002822 if (inPicMode() && ABI.IsO32()) {
2823 MCValue Res;
2824 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2825 Error(IDLoc, "expected relocatable expression");
2826 return true;
2827 }
2828 if (Res.getSymB() != nullptr) {
2829 Error(IDLoc, "expected relocatable expression with only one symbol");
2830 return true;
2831 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002832
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002833 // The case where the result register is $25 is somewhat special. If the
2834 // symbol in the final relocation is external and not modified with a
2835 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2836 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002837 Res.getConstant() == 0 &&
2838 !(Res.getSymA()->getSymbol().isInSection() ||
2839 Res.getSymA()->getSymbol().isTemporary() ||
2840 (Res.getSymA()->getSymbol().isELF() &&
2841 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2842 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002843 const MCExpr *CallExpr =
2844 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2845 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2846 MCOperand::createExpr(CallExpr), IDLoc, STI);
2847 return false;
2848 }
2849
2850 // The remaining cases are:
2851 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2852 // >addiu $tmp, $tmp, %lo(offset)
2853 // >addiu $rd, $tmp, $rs
2854 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2855 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2856 // >addiu $rd, $tmp, $rs
2857 // The addiu's marked with a '>' may be omitted if they are redundant. If
2858 // this happens then the last instruction must use $rd as the result
2859 // register.
2860 const MipsMCExpr *GotExpr =
2861 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2862 const MCExpr *LoExpr = nullptr;
2863 if (Res.getSymA()->getSymbol().isInSection() ||
2864 Res.getSymA()->getSymbol().isTemporary())
2865 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2866 else if (Res.getConstant() != 0) {
2867 // External symbols fully resolve the symbol with just the %got(symbol)
2868 // but we must still account for any offset to the symbol for expressions
2869 // like symbol+8.
2870 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2871 }
2872
2873 unsigned TmpReg = DstReg;
2874 if (UseSrcReg &&
2875 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2876 SrcReg)) {
2877 // If $rs is the same as $rd, we need to use AT.
2878 // If it is not available we exit.
2879 unsigned ATReg = getATReg(IDLoc);
2880 if (!ATReg)
2881 return true;
2882 TmpReg = ATReg;
2883 }
2884
2885 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2886 MCOperand::createExpr(GotExpr), IDLoc, STI);
2887
2888 if (LoExpr)
2889 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2890 IDLoc, STI);
2891
2892 if (UseSrcReg)
2893 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2894
2895 return false;
2896 }
2897
Simon Dardisda96c432017-06-30 15:44:27 +00002898 if (inPicMode() && ABI.ArePtrs64bit()) {
2899 MCValue Res;
2900 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2901 Error(IDLoc, "expected relocatable expression");
2902 return true;
2903 }
2904 if (Res.getSymB() != nullptr) {
2905 Error(IDLoc, "expected relocatable expression with only one symbol");
2906 return true;
2907 }
2908
2909 // The case where the result register is $25 is somewhat special. If the
2910 // symbol in the final relocation is external and not modified with a
2911 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2912 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2913 Res.getConstant() == 0 &&
2914 !(Res.getSymA()->getSymbol().isInSection() ||
2915 Res.getSymA()->getSymbol().isTemporary() ||
2916 (Res.getSymA()->getSymbol().isELF() &&
2917 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2918 ELF::STB_LOCAL))) {
2919 const MCExpr *CallExpr =
2920 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2921 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2922 MCOperand::createExpr(CallExpr), IDLoc, STI);
2923 return false;
2924 }
2925
2926 // The remaining cases are:
2927 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2928 // >daddiu $tmp, $tmp, offset
2929 // >daddu $rd, $tmp, $rs
2930 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2931 // this happens then the last instruction must use $rd as the result
2932 // register.
2933 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2934 Res.getSymA(),
2935 getContext());
2936 const MCExpr *LoExpr = nullptr;
2937 if (Res.getConstant() != 0) {
2938 // Symbols fully resolve with just the %got_disp(symbol) but we
2939 // must still account for any offset to the symbol for
2940 // expressions like symbol+8.
2941 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2942
2943 // FIXME: Offsets greater than 16 bits are not yet implemented.
2944 // FIXME: The correct range is a 32-bit sign-extended number.
2945 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2946 Error(IDLoc, "macro instruction uses large offset, which is not "
2947 "currently supported");
2948 return true;
2949 }
2950 }
2951
2952 unsigned TmpReg = DstReg;
2953 if (UseSrcReg &&
2954 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2955 SrcReg)) {
2956 // If $rs is the same as $rd, we need to use AT.
2957 // If it is not available we exit.
2958 unsigned ATReg = getATReg(IDLoc);
2959 if (!ATReg)
2960 return true;
2961 TmpReg = ATReg;
2962 }
2963
2964 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2965 MCOperand::createExpr(GotExpr), IDLoc, STI);
2966
2967 if (LoExpr)
2968 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2969 IDLoc, STI);
2970
2971 if (UseSrcReg)
2972 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2973
2974 return false;
2975 }
2976
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002977 const MipsMCExpr *HiExpr =
2978 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2979 const MipsMCExpr *LoExpr =
2980 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002981
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002982 // This is the 64-bit symbol address expansion.
2983 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002984 // We need AT for the 64-bit expansion in the cases where the optional
2985 // source register is the destination register and for the superscalar
2986 // scheduled form.
2987 //
2988 // If it is not available we exit if the destination is the same as the
2989 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002990
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002991 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002992 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002993 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002994 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002995
Simon Dardis3aa8a902017-02-06 12:43:46 +00002996 bool RdRegIsRsReg =
2997 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2998
2999 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3000 unsigned ATReg = getATReg(IDLoc);
3001
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003002 // If $rs is the same as $rd:
3003 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3004 // daddiu $at, $at, %higher(sym)
3005 // dsll $at, $at, 16
3006 // daddiu $at, $at, %hi(sym)
3007 // dsll $at, $at, 16
3008 // daddiu $at, $at, %lo(sym)
3009 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003010 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3011 STI);
3012 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3013 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3014 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3015 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3016 IDLoc, STI);
3017 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3018 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3019 IDLoc, STI);
3020 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003021
3022 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003023 } else if (canUseATReg() && !RdRegIsRsReg) {
3024 unsigned ATReg = getATReg(IDLoc);
3025
3026 // If the $rs is different from $rd or if $rs isn't specified and we
3027 // have $at available:
3028 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3029 // lui $at, %hi(sym)
3030 // daddiu $rd, $rd, %higher(sym)
3031 // daddiu $at, $at, %lo(sym)
3032 // dsll32 $rd, $rd, 0
3033 // daddu $rd, $rd, $at
3034 // (daddu $rd, $rd, $rs)
3035 //
3036 // Which is preferred for superscalar issue.
3037 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3038 STI);
3039 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3040 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3041 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3042 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3043 IDLoc, STI);
3044 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3045 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3046 if (UseSrcReg)
3047 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3048
3049 return false;
3050 } else if (!canUseATReg() && !RdRegIsRsReg) {
3051 // Otherwise, synthesize the address in the destination register
3052 // serially:
3053 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3054 // daddiu $rd, $rd, %higher(sym)
3055 // dsll $rd, $rd, 16
3056 // daddiu $rd, $rd, %hi(sym)
3057 // dsll $rd, $rd, 16
3058 // daddiu $rd, $rd, %lo(sym)
3059 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3060 STI);
3061 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3062 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3063 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3064 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3065 MCOperand::createExpr(HiExpr), IDLoc, STI);
3066 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3067 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3068 MCOperand::createExpr(LoExpr), IDLoc, STI);
3069 if (UseSrcReg)
3070 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3071
3072 return false;
3073 } else {
3074 // We have a case where SrcReg == DstReg and we don't have $at
3075 // available. We can't expand this case, so error out appropriately.
3076 assert(SrcReg == DstReg && !canUseATReg() &&
3077 "Could have expanded dla but didn't?");
3078 reportParseError(IDLoc,
3079 "pseudo-instruction requires $at, which is not available");
3080 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003081 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003082 }
3083
3084 // And now, the 32-bit symbol address expansion:
3085 // If $rs is the same as $rd:
3086 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3087 // ori $at, $at, %lo(sym)
3088 // addu $rd, $at, $rd
3089 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3090 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3091 // ori $rd, $rd, %lo(sym)
3092 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003093 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003094 if (UseSrcReg &&
3095 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003096 // If $rs is the same as $rd, we need to use AT.
3097 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003098 unsigned ATReg = getATReg(IDLoc);
3099 if (!ATReg)
3100 return true;
3101 TmpReg = ATReg;
3102 }
3103
Daniel Sandersa736b372016-04-29 13:33:12 +00003104 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3105 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3106 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003107
Toma Tabacufb9d1252015-06-22 12:08:39 +00003108 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003109 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003110 else
Scott Egerton24557012016-01-21 15:11:01 +00003111 assert(
3112 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003113
Toma Tabacu674825c2015-06-16 12:16:24 +00003114 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003115}
3116
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003117// Each double-precision register DO-D15 overlaps with two of the single
3118// precision registers F0-F31. As an example, all of the following hold true:
3119// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3120static unsigned nextReg(unsigned Reg) {
3121 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3122 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3123 switch (Reg) {
3124 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3125 case Mips::ZERO: return Mips::AT;
3126 case Mips::AT: return Mips::V0;
3127 case Mips::V0: return Mips::V1;
3128 case Mips::V1: return Mips::A0;
3129 case Mips::A0: return Mips::A1;
3130 case Mips::A1: return Mips::A2;
3131 case Mips::A2: return Mips::A3;
3132 case Mips::A3: return Mips::T0;
3133 case Mips::T0: return Mips::T1;
3134 case Mips::T1: return Mips::T2;
3135 case Mips::T2: return Mips::T3;
3136 case Mips::T3: return Mips::T4;
3137 case Mips::T4: return Mips::T5;
3138 case Mips::T5: return Mips::T6;
3139 case Mips::T6: return Mips::T7;
3140 case Mips::T7: return Mips::S0;
3141 case Mips::S0: return Mips::S1;
3142 case Mips::S1: return Mips::S2;
3143 case Mips::S2: return Mips::S3;
3144 case Mips::S3: return Mips::S4;
3145 case Mips::S4: return Mips::S5;
3146 case Mips::S5: return Mips::S6;
3147 case Mips::S6: return Mips::S7;
3148 case Mips::S7: return Mips::T8;
3149 case Mips::T8: return Mips::T9;
3150 case Mips::T9: return Mips::K0;
3151 case Mips::K0: return Mips::K1;
3152 case Mips::K1: return Mips::GP;
3153 case Mips::GP: return Mips::SP;
3154 case Mips::SP: return Mips::FP;
3155 case Mips::FP: return Mips::RA;
3156 case Mips::RA: return Mips::ZERO;
3157 case Mips::D0: return Mips::F1;
3158 case Mips::D1: return Mips::F3;
3159 case Mips::D2: return Mips::F5;
3160 case Mips::D3: return Mips::F7;
3161 case Mips::D4: return Mips::F9;
3162 case Mips::D5: return Mips::F11;
3163 case Mips::D6: return Mips::F13;
3164 case Mips::D7: return Mips::F15;
3165 case Mips::D8: return Mips::F17;
3166 case Mips::D9: return Mips::F19;
3167 case Mips::D10: return Mips::F21;
3168 case Mips::D11: return Mips::F23;
3169 case Mips::D12: return Mips::F25;
3170 case Mips::D13: return Mips::F27;
3171 case Mips::D14: return Mips::F29;
3172 case Mips::D15: return Mips::F31;
3173 }
3174}
3175
3176// FIXME: This method is too general. In principle we should compute the number
3177// of instructions required to synthesize the immediate inline compared to
3178// synthesizing the address inline and relying on non .text sections.
3179// For static O32 and N32 this may yield a small benefit, for static N64 this is
3180// likely to yield a much larger benefit as we have to synthesize a 64bit
3181// address to load a 64 bit value.
3182bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3183 MCSymbol *Sym) {
3184 unsigned ATReg = getATReg(IDLoc);
3185 if (!ATReg)
3186 return true;
3187
3188 if(IsPicEnabled) {
3189 const MCExpr *GotSym =
3190 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3191 const MipsMCExpr *GotExpr =
3192 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3193
3194 if(isABI_O32() || isABI_N32()) {
3195 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3196 IDLoc, STI);
3197 } else { //isABI_N64()
3198 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3199 IDLoc, STI);
3200 }
3201 } else { //!IsPicEnabled
3202 const MCExpr *HiSym =
3203 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3204 const MipsMCExpr *HiExpr =
3205 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3206
3207 // FIXME: This is technically correct but gives a different result to gas,
3208 // but gas is incomplete there (it has a fixme noting it doesn't work with
3209 // 64-bit addresses).
3210 // FIXME: With -msym32 option, the address expansion for N64 should probably
3211 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3212 // symbol's value is considered sign extended.
3213 if(isABI_O32() || isABI_N32()) {
3214 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3215 } else { //isABI_N64()
3216 const MCExpr *HighestSym =
3217 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3218 const MipsMCExpr *HighestExpr =
3219 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3220 const MCExpr *HigherSym =
3221 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3222 const MipsMCExpr *HigherExpr =
3223 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3224
3225 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3226 STI);
3227 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3228 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3229 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3230 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3231 IDLoc, STI);
3232 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3233 }
3234 }
3235 return false;
3236}
3237
3238bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3239 bool Is64FPU, SMLoc IDLoc,
3240 MCStreamer &Out,
3241 const MCSubtargetInfo *STI) {
3242 MipsTargetStreamer &TOut = getTargetStreamer();
3243 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3244 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3245 "Invalid instruction operand.");
3246
3247 unsigned FirstReg = Inst.getOperand(0).getReg();
3248 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3249
3250 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3251 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3252 // exponent field), convert it to double (e.g. 1 to 1.0)
3253 if ((HiImmOp64 & 0x7ff00000) == 0) {
3254 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3255 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3256 }
3257
3258 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3259 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3260
3261 if (IsSingle) {
3262 // Conversion of a double in an uint64_t to a float in a uint32_t,
3263 // retaining the bit pattern of a float.
3264 uint32_t ImmOp32;
3265 double doubleImm = BitsToDouble(ImmOp64);
3266 float tmp_float = static_cast<float>(doubleImm);
3267 ImmOp32 = FloatToBits(tmp_float);
3268
3269 if (IsGPR) {
3270 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3271 Out, STI))
3272 return true;
3273 return false;
3274 } else {
3275 unsigned ATReg = getATReg(IDLoc);
3276 if (!ATReg)
3277 return true;
3278 if (LoImmOp64 == 0) {
3279 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3280 Out, STI))
3281 return true;
3282 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3283 return false;
3284 }
3285
3286 MCSection *CS = getStreamer().getCurrentSectionOnly();
3287 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3288 // where appropriate.
3289 MCSection *ReadOnlySection = getContext().getELFSection(
3290 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3291
3292 MCSymbol *Sym = getContext().createTempSymbol();
3293 const MCExpr *LoSym =
3294 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3295 const MipsMCExpr *LoExpr =
3296 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3297
3298 getStreamer().SwitchSection(ReadOnlySection);
3299 getStreamer().EmitLabel(Sym, IDLoc);
3300 getStreamer().EmitIntValue(ImmOp32, 4);
3301 getStreamer().SwitchSection(CS);
3302
3303 if(emitPartialAddress(TOut, IDLoc, Sym))
3304 return true;
3305 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3306 MCOperand::createExpr(LoExpr), IDLoc, STI);
3307 }
3308 return false;
3309 }
3310
3311 // if(!IsSingle)
3312 unsigned ATReg = getATReg(IDLoc);
3313 if (!ATReg)
3314 return true;
3315
3316 if (IsGPR) {
3317 if (LoImmOp64 == 0) {
3318 if(isABI_N32() || isABI_N64()) {
3319 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3320 IDLoc, Out, STI))
3321 return true;
3322 return false;
3323 } else {
3324 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3325 IDLoc, Out, STI))
3326 return true;
3327
3328 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3329 IDLoc, Out, STI))
3330 return true;
3331 return false;
3332 }
3333 }
3334
3335 MCSection *CS = getStreamer().getCurrentSectionOnly();
3336 MCSection *ReadOnlySection = getContext().getELFSection(
3337 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3338
3339 MCSymbol *Sym = getContext().createTempSymbol();
3340 const MCExpr *LoSym =
3341 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3342 const MipsMCExpr *LoExpr =
3343 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3344
3345 getStreamer().SwitchSection(ReadOnlySection);
3346 getStreamer().EmitLabel(Sym, IDLoc);
3347 getStreamer().EmitIntValue(HiImmOp64, 4);
3348 getStreamer().EmitIntValue(LoImmOp64, 4);
3349 getStreamer().SwitchSection(CS);
3350
3351 if(emitPartialAddress(TOut, IDLoc, Sym))
3352 return true;
3353 if(isABI_N64())
3354 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3355 MCOperand::createExpr(LoExpr), IDLoc, STI);
3356 else
3357 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3358 MCOperand::createExpr(LoExpr), IDLoc, STI);
3359
3360 if(isABI_N32() || isABI_N64())
3361 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3362 else {
3363 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3364 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3365 }
3366 return false;
3367 } else { // if(!IsGPR && !IsSingle)
3368 if ((LoImmOp64 == 0) &&
3369 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3370 // FIXME: In the case where the constant is zero, we can load the
3371 // register directly from the zero register.
3372 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3373 Out, STI))
3374 return true;
3375 if (isABI_N32() || isABI_N64())
3376 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3377 else if (hasMips32r2()) {
3378 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3379 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3380 } else {
3381 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3382 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3383 }
3384 return false;
3385 }
3386
3387 MCSection *CS = getStreamer().getCurrentSectionOnly();
3388 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3389 // where appropriate.
3390 MCSection *ReadOnlySection = getContext().getELFSection(
3391 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3392
3393 MCSymbol *Sym = getContext().createTempSymbol();
3394 const MCExpr *LoSym =
3395 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3396 const MipsMCExpr *LoExpr =
3397 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3398
3399 getStreamer().SwitchSection(ReadOnlySection);
3400 getStreamer().EmitLabel(Sym, IDLoc);
3401 getStreamer().EmitIntValue(HiImmOp64, 4);
3402 getStreamer().EmitIntValue(LoImmOp64, 4);
3403 getStreamer().SwitchSection(CS);
3404
3405 if(emitPartialAddress(TOut, IDLoc, Sym))
3406 return true;
3407 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3408 MCOperand::createExpr(LoExpr), IDLoc, STI);
3409 }
3410 return false;
3411}
3412
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003413bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3414 MCStreamer &Out,
3415 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003416 MipsTargetStreamer &TOut = getTargetStreamer();
3417
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003418 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3419 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003420
3421 MCOperand Offset = Inst.getOperand(0);
3422 if (Offset.isExpr()) {
3423 Inst.clear();
3424 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003425 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3426 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3427 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003428 } else {
3429 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003430 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003431 // If offset fits into 11 bits then this instruction becomes microMIPS
3432 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003433 if (inMicroMipsMode())
3434 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003435 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003436 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003437 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003438 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003439 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003440 Inst.clear();
3441 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003442 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3443 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3444 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003445 }
3446 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003447 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003448
Zoran Jovanovicada70912015-09-07 11:56:37 +00003449 // If .set reorder is active and branch instruction has a delay slot,
3450 // emit a NOP after it.
3451 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3452 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003453 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003454
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003455 return false;
3456}
3457
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003458bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3459 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003460 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003461 const MCOperand &DstRegOp = Inst.getOperand(0);
3462 assert(DstRegOp.isReg() && "expected register operand kind");
3463
3464 const MCOperand &ImmOp = Inst.getOperand(1);
3465 assert(ImmOp.isImm() && "expected immediate operand kind");
3466
3467 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003468 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3469 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003470
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003471 bool IsLikely = false;
3472
Toma Tabacue1e460d2015-06-11 10:36:10 +00003473 unsigned OpCode = 0;
3474 switch(Inst.getOpcode()) {
3475 case Mips::BneImm:
3476 OpCode = Mips::BNE;
3477 break;
3478 case Mips::BeqImm:
3479 OpCode = Mips::BEQ;
3480 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003481 case Mips::BEQLImmMacro:
3482 OpCode = Mips::BEQL;
3483 IsLikely = true;
3484 break;
3485 case Mips::BNELImmMacro:
3486 OpCode = Mips::BNEL;
3487 IsLikely = true;
3488 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003489 default:
3490 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3491 break;
3492 }
3493
3494 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003495 if (ImmValue == 0) {
3496 if (IsLikely) {
3497 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3498 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3499 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3500 } else
3501 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3502 STI);
3503 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003504 warnIfNoMacro(IDLoc);
3505
3506 unsigned ATReg = getATReg(IDLoc);
3507 if (!ATReg)
3508 return true;
3509
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003510 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003511 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003512 return true;
3513
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003514 if (IsLikely) {
3515 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3516 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3517 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3518 } else
3519 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003520 }
3521 return false;
3522}
3523
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003524void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003525 const MCSubtargetInfo *STI, bool IsLoad,
3526 bool IsImmOpnd) {
3527 if (IsLoad) {
3528 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3529 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003530 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003531 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3532}
3533
3534void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3535 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3536 MipsTargetStreamer &TOut = getTargetStreamer();
3537
3538 unsigned DstReg = Inst.getOperand(0).getReg();
3539 unsigned BaseReg = Inst.getOperand(1).getReg();
3540
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003541 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003542 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3543 unsigned DstRegClassID =
3544 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3545 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3546 (DstRegClassID == Mips::GPR64RegClassID);
3547
3548 if (IsImmOpnd) {
3549 // Try to use DstReg as the temporary.
3550 if (IsGPR && (BaseReg != DstReg)) {
3551 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3552 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3553 STI);
3554 return;
3555 }
3556
Matheus Almeida7de68e72014-06-18 14:46:05 +00003557 // At this point we need AT to perform the expansions and we exit if it is
3558 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003559 unsigned ATReg = getATReg(IDLoc);
3560 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003561 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003562
3563 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3564 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3565 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003566 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003567
Daniel Sandersfba875f2016-04-29 13:43:45 +00003568 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003569 MCOperand LoOperand = MCOperand::createExpr(
3570 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3571 MCOperand HiOperand = MCOperand::createExpr(
3572 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003573
3574 // Try to use DstReg as the temporary.
3575 if (IsGPR && (BaseReg != DstReg)) {
3576 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3577 LoOperand, DstReg, IDLoc, STI);
3578 return;
3579 }
3580
3581 // At this point we need AT to perform the expansions and we exit if it is
3582 // not available.
3583 unsigned ATReg = getATReg(IDLoc);
3584 if (!ATReg)
3585 return;
3586
3587 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3588 LoOperand, ATReg, IDLoc, STI);
3589}
3590
3591void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3592 const MCSubtargetInfo *STI,
3593 bool IsImmOpnd) {
3594 MipsTargetStreamer &TOut = getTargetStreamer();
3595
3596 unsigned SrcReg = Inst.getOperand(0).getReg();
3597 unsigned BaseReg = Inst.getOperand(1).getReg();
3598
Daniel Sanders241c6792016-05-12 14:01:50 +00003599 if (IsImmOpnd) {
3600 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3601 Inst.getOperand(2).getImm(),
3602 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3603 return;
3604 }
3605
Daniel Sandersfba875f2016-04-29 13:43:45 +00003606 unsigned ATReg = getATReg(IDLoc);
3607 if (!ATReg)
3608 return;
3609
Daniel Sandersfba875f2016-04-29 13:43:45 +00003610 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003611 MCOperand LoOperand = MCOperand::createExpr(
3612 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3613 MCOperand HiOperand = MCOperand::createExpr(
3614 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003615 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3616 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003617}
3618
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003619bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3620 MCStreamer &Out,
3621 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003622 unsigned OpNum = Inst.getNumOperands();
3623 unsigned Opcode = Inst.getOpcode();
3624 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3625
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003626 assert(Inst.getOperand(OpNum - 1).isImm() &&
3627 Inst.getOperand(OpNum - 2).isReg() &&
3628 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003629
3630 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3631 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003632 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3633 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3634 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3635 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003636 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003637 if (inMicroMipsMode() && hasMips32r6())
3638 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3639 else
3640 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3641 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003642
3643 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003644 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003645 return false;
3646}
3647
Toma Tabacu1a108322015-06-17 13:20:24 +00003648bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003649 MCStreamer &Out,
3650 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003651 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003652 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003653 unsigned PseudoOpcode = Inst.getOpcode();
3654 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003655 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003656 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3657
3658 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003659 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003660
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003661 unsigned TrgReg;
3662 if (TrgOp.isReg())
3663 TrgReg = TrgOp.getReg();
3664 else if (TrgOp.isImm()) {
3665 warnIfNoMacro(IDLoc);
3666 EmittedNoMacroWarning = true;
3667
3668 TrgReg = getATReg(IDLoc);
3669 if (!TrgReg)
3670 return true;
3671
3672 switch(PseudoOpcode) {
3673 default:
3674 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3675 case Mips::BLTImmMacro:
3676 PseudoOpcode = Mips::BLT;
3677 break;
3678 case Mips::BLEImmMacro:
3679 PseudoOpcode = Mips::BLE;
3680 break;
3681 case Mips::BGEImmMacro:
3682 PseudoOpcode = Mips::BGE;
3683 break;
3684 case Mips::BGTImmMacro:
3685 PseudoOpcode = Mips::BGT;
3686 break;
3687 case Mips::BLTUImmMacro:
3688 PseudoOpcode = Mips::BLTU;
3689 break;
3690 case Mips::BLEUImmMacro:
3691 PseudoOpcode = Mips::BLEU;
3692 break;
3693 case Mips::BGEUImmMacro:
3694 PseudoOpcode = Mips::BGEU;
3695 break;
3696 case Mips::BGTUImmMacro:
3697 PseudoOpcode = Mips::BGTU;
3698 break;
3699 case Mips::BLTLImmMacro:
3700 PseudoOpcode = Mips::BLTL;
3701 break;
3702 case Mips::BLELImmMacro:
3703 PseudoOpcode = Mips::BLEL;
3704 break;
3705 case Mips::BGELImmMacro:
3706 PseudoOpcode = Mips::BGEL;
3707 break;
3708 case Mips::BGTLImmMacro:
3709 PseudoOpcode = Mips::BGTL;
3710 break;
3711 case Mips::BLTULImmMacro:
3712 PseudoOpcode = Mips::BLTUL;
3713 break;
3714 case Mips::BLEULImmMacro:
3715 PseudoOpcode = Mips::BLEUL;
3716 break;
3717 case Mips::BGEULImmMacro:
3718 PseudoOpcode = Mips::BGEUL;
3719 break;
3720 case Mips::BGTULImmMacro:
3721 PseudoOpcode = Mips::BGTUL;
3722 break;
3723 }
3724
3725 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003726 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003727 return true;
3728 }
3729
Toma Tabacu1a108322015-06-17 13:20:24 +00003730 switch (PseudoOpcode) {
3731 case Mips::BLT:
3732 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003733 case Mips::BLTL:
3734 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003735 AcceptsEquality = false;
3736 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003737 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3738 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003739 ZeroSrcOpcode = Mips::BGTZ;
3740 ZeroTrgOpcode = Mips::BLTZ;
3741 break;
3742 case Mips::BLE:
3743 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003744 case Mips::BLEL:
3745 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003746 AcceptsEquality = true;
3747 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003748 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3749 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003750 ZeroSrcOpcode = Mips::BGEZ;
3751 ZeroTrgOpcode = Mips::BLEZ;
3752 break;
3753 case Mips::BGE:
3754 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003755 case Mips::BGEL:
3756 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003757 AcceptsEquality = true;
3758 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003759 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3760 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003761 ZeroSrcOpcode = Mips::BLEZ;
3762 ZeroTrgOpcode = Mips::BGEZ;
3763 break;
3764 case Mips::BGT:
3765 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003766 case Mips::BGTL:
3767 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003768 AcceptsEquality = false;
3769 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003770 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3771 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003772 ZeroSrcOpcode = Mips::BLTZ;
3773 ZeroTrgOpcode = Mips::BGTZ;
3774 break;
3775 default:
3776 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3777 }
3778
Toma Tabacu1a108322015-06-17 13:20:24 +00003779 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3780 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3781 if (IsSrcRegZero && IsTrgRegZero) {
3782 // FIXME: All of these Opcode-specific if's are needed for compatibility
3783 // with GAS' behaviour. However, they may not generate the most efficient
3784 // code in some circumstances.
3785 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003786 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3787 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003788 return false;
3789 }
3790 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003791 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3792 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003793 Warning(IDLoc, "branch is always taken");
3794 return false;
3795 }
3796 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003797 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3798 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003799 Warning(IDLoc, "branch is always taken");
3800 return false;
3801 }
3802 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003803 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3804 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003805 return false;
3806 }
3807 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003808 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3809 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003810 return false;
3811 }
3812 if (AcceptsEquality) {
3813 // If both registers are $0 and the pseudo-branch accepts equality, it
3814 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003815 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3816 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003817 Warning(IDLoc, "branch is always taken");
3818 return false;
3819 }
3820 // If both registers are $0 and the pseudo-branch does not accept
3821 // equality, it will never be taken, so we don't have to emit anything.
3822 return false;
3823 }
3824 if (IsSrcRegZero || IsTrgRegZero) {
3825 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3826 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3827 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3828 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3829 // the pseudo-branch will never be taken, so we don't emit anything.
3830 // This only applies to unsigned pseudo-branches.
3831 return false;
3832 }
3833 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3834 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3835 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3836 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3837 // the pseudo-branch will always be taken, so we emit an unconditional
3838 // branch.
3839 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003840 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3841 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003842 Warning(IDLoc, "branch is always taken");
3843 return false;
3844 }
3845 if (IsUnsigned) {
3846 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3847 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3848 // the pseudo-branch will be taken only when the non-zero register is
3849 // different from 0, so we emit a BNEZ.
3850 //
3851 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3852 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3853 // the pseudo-branch will be taken only when the non-zero register is
3854 // equal to 0, so we emit a BEQZ.
3855 //
3856 // Because only BLEU and BGEU branch on equality, we can use the
3857 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003858 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3859 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3860 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003861 return false;
3862 }
3863 // If we have a signed pseudo-branch and one of the registers is $0,
3864 // we can use an appropriate compare-to-zero branch. We select which one
3865 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003866 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3867 IsSrcRegZero ? TrgReg : SrcReg,
3868 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003869 return false;
3870 }
3871
3872 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3873 // expansions. If it is not available, we return.
3874 unsigned ATRegNum = getATReg(IDLoc);
3875 if (!ATRegNum)
3876 return true;
3877
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003878 if (!EmittedNoMacroWarning)
3879 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003880
3881 // SLT fits well with 2 of our 4 pseudo-branches:
3882 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3883 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3884 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3885 // This is accomplished by using a BNEZ with the result of the SLT.
3886 //
3887 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003888 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003889 // Because only BGE and BLE branch on equality, we can use the
3890 // AcceptsEquality variable to decide when to emit the BEQZ.
3891 // Note that the order of the SLT arguments doesn't change between
3892 // opposites.
3893 //
3894 // The same applies to the unsigned variants, except that SLTu is used
3895 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003896 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3897 ReverseOrderSLT ? TrgReg : SrcReg,
3898 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003899
Daniel Sandersa736b372016-04-29 13:33:12 +00003900 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3901 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3902 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3903 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003904 return false;
3905}
3906
Simon Dardis509da1a2017-02-13 16:06:48 +00003907// Expand a integer division macro.
3908//
3909// Notably we don't have to emit a warning when encountering $rt as the $zero
3910// register, or 0 as an immediate. processInstruction() has already done that.
3911//
3912// The destination register can only be $zero when expanding (S)DivIMacro or
3913// D(S)DivMacro.
3914
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003915bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3916 const MCSubtargetInfo *STI, const bool IsMips64,
3917 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003918 MipsTargetStreamer &TOut = getTargetStreamer();
3919
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003920 warnIfNoMacro(IDLoc);
3921
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003922 const MCOperand &RdRegOp = Inst.getOperand(0);
3923 assert(RdRegOp.isReg() && "expected register operand kind");
3924 unsigned RdReg = RdRegOp.getReg();
3925
3926 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003927 assert(RsRegOp.isReg() && "expected register operand kind");
3928 unsigned RsReg = RsRegOp.getReg();
3929
Simon Dardis12850ee2017-01-31 10:49:24 +00003930 unsigned RtReg;
3931 int64_t ImmValue;
3932
3933 const MCOperand &RtOp = Inst.getOperand(2);
3934 assert((RtOp.isReg() || RtOp.isImm()) &&
3935 "expected register or immediate operand kind");
3936 if (RtOp.isReg())
3937 RtReg = RtOp.getReg();
3938 else
3939 ImmValue = RtOp.getImm();
3940
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003941 unsigned DivOp;
3942 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003943 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003944
3945 if (IsMips64) {
3946 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3947 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003948 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003949 } else {
3950 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3951 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003952 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003953 }
3954
3955 bool UseTraps = useTraps();
3956
Simon Dardis12850ee2017-01-31 10:49:24 +00003957 if (RtOp.isImm()) {
3958 unsigned ATReg = getATReg(IDLoc);
3959 if (!ATReg)
3960 return true;
3961
3962 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003963 if (UseTraps)
3964 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3965 else
3966 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3967 return false;
3968 }
3969
3970 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003971 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003972 return false;
3973 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003974 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003975 return false;
3976 } else {
3977 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3978 false, Inst.getLoc(), Out, STI))
3979 return true;
3980 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3981 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3982 return false;
3983 }
3984 return true;
3985 }
3986
Simon Dardis509da1a2017-02-13 16:06:48 +00003987 // If the macro expansion of (d)div(u) would always trap or break, insert
3988 // the trap/break and exit. This gives a different result to GAS. GAS has
3989 // an inconsistency/missed optimization in that not all cases are handled
3990 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003991 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003992 if (UseTraps) {
3993 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003994 return false;
3995 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003996 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3997 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003998 }
3999
Simon Dardis509da1a2017-02-13 16:06:48 +00004000 // Temporary label for first branch traget
4001 MCContext &Context = TOut.getStreamer().getContext();
4002 MCSymbol *BrTarget;
4003 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004004
4005 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004006 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004007 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004008 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004009 BrTarget = Context.createTempSymbol();
4010 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4011 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004012 }
4013
Daniel Sandersa736b372016-04-29 13:33:12 +00004014 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004015
4016 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004017 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004018
4019 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004020 if (!UseTraps)
4021 TOut.getStreamer().EmitLabel(BrTarget);
4022
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004023 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004024 return false;
4025 }
4026
4027 unsigned ATReg = getATReg(IDLoc);
4028 if (!ATReg)
4029 return true;
4030
Simon Dardis509da1a2017-02-13 16:06:48 +00004031 if (!UseTraps)
4032 TOut.getStreamer().EmitLabel(BrTarget);
4033
Daniel Sandersa736b372016-04-29 13:33:12 +00004034 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004035
4036 // Temporary label for the second branch target.
4037 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4038 MCOperand LabelOpEnd =
4039 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4040
4041 // Branch to the mflo instruction.
4042 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4043
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004044 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004045 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4046 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004047 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004048 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004049 }
4050
4051 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004052 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004053 else {
4054 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004055 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004056 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4057 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004058 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004059
4060 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004061 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004062 return false;
4063}
4064
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004065bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004066 SMLoc IDLoc, MCStreamer &Out,
4067 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004068 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004069
4070 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4071 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4072 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4073
4074 unsigned FirstReg = Inst.getOperand(0).getReg();
4075 unsigned SecondReg = Inst.getOperand(1).getReg();
4076 unsigned ThirdReg = Inst.getOperand(2).getReg();
4077
4078 if (hasMips1() && !hasMips2()) {
4079 unsigned ATReg = getATReg(IDLoc);
4080 if (!ATReg)
4081 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004082 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4083 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4084 TOut.emitNop(IDLoc, STI);
4085 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4086 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4087 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4088 TOut.emitNop(IDLoc, STI);
4089 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4090 : Mips::CVT_W_S,
4091 FirstReg, SecondReg, IDLoc, STI);
4092 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4093 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004094 return false;
4095 }
4096
Daniel Sandersa736b372016-04-29 13:33:12 +00004097 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4098 : Mips::TRUNC_W_S,
4099 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004100
4101 return false;
4102}
4103
Daniel Sanders6394ee52015-10-15 14:52:58 +00004104bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004105 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004106 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004107 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004108 }
4109
Toma Tabacud88d79c2015-06-23 14:39:42 +00004110 const MCOperand &DstRegOp = Inst.getOperand(0);
4111 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004112 const MCOperand &SrcRegOp = Inst.getOperand(1);
4113 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004114 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4115 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4116
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004117 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004118 unsigned DstReg = DstRegOp.getReg();
4119 unsigned SrcReg = SrcRegOp.getReg();
4120 int64_t OffsetValue = OffsetImmOp.getImm();
4121
4122 // NOTE: We always need AT for ULHU, as it is always used as the source
4123 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004124 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004125 unsigned ATReg = getATReg(IDLoc);
4126 if (!ATReg)
4127 return true;
4128
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004129 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4130 if (IsLargeOffset) {
4131 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4132 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004133 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004134 }
4135
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004136 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4137 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4138 if (isLittle())
4139 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004140
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004141 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4142 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004143
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004144 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4145 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004146
Daniel Sandersa736b372016-04-29 13:33:12 +00004147 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004148 FirstOffset, IDLoc, STI);
4149 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004150 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004151 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004152
4153 return false;
4154}
4155
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004156bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004157 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004158 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004159 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004160 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004161
4162 const MCOperand &DstRegOp = Inst.getOperand(0);
4163 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004164 const MCOperand &SrcRegOp = Inst.getOperand(1);
4165 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004166 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4167 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4168
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004169 MipsTargetStreamer &TOut = getTargetStreamer();
4170 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004171 unsigned SrcReg = SrcRegOp.getReg();
4172 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004173
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004174 warnIfNoMacro(IDLoc);
4175 unsigned ATReg = getATReg(IDLoc);
4176 if (!ATReg)
4177 return true;
4178
4179 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4180 if (IsLargeOffset) {
4181 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4182 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004183 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004184 }
4185
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004186 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4187 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4188 if (isLittle())
4189 std::swap(FirstOffset, SecondOffset);
4190
4191 if (IsLargeOffset) {
4192 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4193 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4194 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4195 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4196 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4197 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004198 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004199 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4200 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4201 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004202 }
4203
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004204 return false;
4205}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004206
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004207bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4208 const MCSubtargetInfo *STI) {
4209 if (hasMips32r6() || hasMips64r6()) {
4210 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4211 }
4212
4213 const MCOperand &DstRegOp = Inst.getOperand(0);
4214 assert(DstRegOp.isReg() && "expected register operand kind");
4215 const MCOperand &SrcRegOp = Inst.getOperand(1);
4216 assert(SrcRegOp.isReg() && "expected register operand kind");
4217 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4218 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4219
4220 MipsTargetStreamer &TOut = getTargetStreamer();
4221 unsigned DstReg = DstRegOp.getReg();
4222 unsigned SrcReg = SrcRegOp.getReg();
4223 int64_t OffsetValue = OffsetImmOp.getImm();
4224
4225 // Compute left/right load/store offsets.
4226 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4227 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4228 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4229 if (isLittle())
4230 std::swap(LxlOffset, LxrOffset);
4231
4232 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4233 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4234 unsigned TmpReg = SrcReg;
4235 if (IsLargeOffset || DoMove) {
4236 warnIfNoMacro(IDLoc);
4237 TmpReg = getATReg(IDLoc);
4238 if (!TmpReg)
4239 return true;
4240 }
4241
4242 if (IsLargeOffset) {
4243 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4244 IDLoc, Out, STI))
4245 return true;
4246 }
4247
4248 if (DoMove)
4249 std::swap(DstReg, TmpReg);
4250
4251 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4252 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4253 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4254 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4255
4256 if (DoMove)
4257 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004258
4259 return false;
4260}
4261
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004262bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004263 MCStreamer &Out,
4264 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004265 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004266
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004267 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4268 assert(Inst.getOperand(0).isReg() &&
4269 Inst.getOperand(1).isReg() &&
4270 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004271
4272 unsigned ATReg = Mips::NoRegister;
4273 unsigned FinalDstReg = Mips::NoRegister;
4274 unsigned DstReg = Inst.getOperand(0).getReg();
4275 unsigned SrcReg = Inst.getOperand(1).getReg();
4276 int64_t ImmValue = Inst.getOperand(2).getImm();
4277
Simon Dardisaa208812017-02-24 14:34:32 +00004278 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004279
4280 unsigned FinalOpcode = Inst.getOpcode();
4281
4282 if (DstReg == SrcReg) {
4283 ATReg = getATReg(Inst.getLoc());
4284 if (!ATReg)
4285 return true;
4286 FinalDstReg = DstReg;
4287 DstReg = ATReg;
4288 }
4289
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004290 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004291 switch (FinalOpcode) {
4292 default:
4293 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004294 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004295 FinalOpcode = Mips::ADD;
4296 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004297 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004298 FinalOpcode = Mips::ADDu;
4299 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004300 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004301 FinalOpcode = Mips::AND;
4302 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004303 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004304 FinalOpcode = Mips::NOR;
4305 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004306 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004307 FinalOpcode = Mips::OR;
4308 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004309 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004310 FinalOpcode = Mips::SLT;
4311 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004312 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004313 FinalOpcode = Mips::SLTu;
4314 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004315 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004316 FinalOpcode = Mips::XOR;
4317 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004318 case Mips::ADDi_MM:
4319 FinalOpcode = Mips::ADD_MM;
4320 break;
4321 case Mips::ADDiu_MM:
4322 FinalOpcode = Mips::ADDu_MM;
4323 break;
4324 case Mips::ANDi_MM:
4325 FinalOpcode = Mips::AND_MM;
4326 break;
4327 case Mips::ORi_MM:
4328 FinalOpcode = Mips::OR_MM;
4329 break;
4330 case Mips::SLTi_MM:
4331 FinalOpcode = Mips::SLT_MM;
4332 break;
4333 case Mips::SLTiu_MM:
4334 FinalOpcode = Mips::SLTu_MM;
4335 break;
4336 case Mips::XORi_MM:
4337 FinalOpcode = Mips::XOR_MM;
4338 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004339 case Mips::ANDi64:
4340 FinalOpcode = Mips::AND64;
4341 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004342 case Mips::NORImm64:
4343 FinalOpcode = Mips::NOR64;
4344 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004345 case Mips::ORi64:
4346 FinalOpcode = Mips::OR64;
4347 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004348 case Mips::SLTImm64:
4349 FinalOpcode = Mips::SLT64;
4350 break;
4351 case Mips::SLTUImm64:
4352 FinalOpcode = Mips::SLTu64;
4353 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004354 case Mips::XORi64:
4355 FinalOpcode = Mips::XOR64;
4356 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004357 }
4358
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004359 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004360 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004361 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004362 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004363 return false;
4364 }
4365 return true;
4366}
4367
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004368bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4369 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004370 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004371 unsigned ATReg = Mips::NoRegister;
4372 unsigned DReg = Inst.getOperand(0).getReg();
4373 unsigned SReg = Inst.getOperand(1).getReg();
4374 unsigned TReg = Inst.getOperand(2).getReg();
4375 unsigned TmpReg = DReg;
4376
4377 unsigned FirstShift = Mips::NOP;
4378 unsigned SecondShift = Mips::NOP;
4379
4380 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004381 if (DReg == SReg) {
4382 TmpReg = getATReg(Inst.getLoc());
4383 if (!TmpReg)
4384 return true;
4385 }
4386
4387 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004388 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4389 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004390 return false;
4391 }
4392
4393 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004394 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004395 return false;
4396 }
4397
4398 return true;
4399 }
4400
4401 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004402 switch (Inst.getOpcode()) {
4403 default:
4404 llvm_unreachable("unexpected instruction opcode");
4405 case Mips::ROL:
4406 FirstShift = Mips::SRLV;
4407 SecondShift = Mips::SLLV;
4408 break;
4409 case Mips::ROR:
4410 FirstShift = Mips::SLLV;
4411 SecondShift = Mips::SRLV;
4412 break;
4413 }
4414
4415 ATReg = getATReg(Inst.getLoc());
4416 if (!ATReg)
4417 return true;
4418
Daniel Sandersa736b372016-04-29 13:33:12 +00004419 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4420 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4421 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4422 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004423
4424 return false;
4425 }
4426
4427 return true;
4428}
4429
4430bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004431 MCStreamer &Out,
4432 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004433 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004434 unsigned ATReg = Mips::NoRegister;
4435 unsigned DReg = Inst.getOperand(0).getReg();
4436 unsigned SReg = Inst.getOperand(1).getReg();
4437 int64_t ImmValue = Inst.getOperand(2).getImm();
4438
4439 unsigned FirstShift = Mips::NOP;
4440 unsigned SecondShift = Mips::NOP;
4441
4442 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004443 if (Inst.getOpcode() == Mips::ROLImm) {
4444 uint64_t MaxShift = 32;
4445 uint64_t ShiftValue = ImmValue;
4446 if (ImmValue != 0)
4447 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004448 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004449 return false;
4450 }
4451
4452 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004453 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004454 return false;
4455 }
4456
4457 return true;
4458 }
4459
4460 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004461 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004462 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004463 return false;
4464 }
4465
4466 switch (Inst.getOpcode()) {
4467 default:
4468 llvm_unreachable("unexpected instruction opcode");
4469 case Mips::ROLImm:
4470 FirstShift = Mips::SLL;
4471 SecondShift = Mips::SRL;
4472 break;
4473 case Mips::RORImm:
4474 FirstShift = Mips::SRL;
4475 SecondShift = Mips::SLL;
4476 break;
4477 }
4478
4479 ATReg = getATReg(Inst.getLoc());
4480 if (!ATReg)
4481 return true;
4482
Daniel Sandersa736b372016-04-29 13:33:12 +00004483 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4484 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4485 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004486
4487 return false;
4488 }
4489
4490 return true;
4491}
4492
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004493bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4494 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004495 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004496 unsigned ATReg = Mips::NoRegister;
4497 unsigned DReg = Inst.getOperand(0).getReg();
4498 unsigned SReg = Inst.getOperand(1).getReg();
4499 unsigned TReg = Inst.getOperand(2).getReg();
4500 unsigned TmpReg = DReg;
4501
4502 unsigned FirstShift = Mips::NOP;
4503 unsigned SecondShift = Mips::NOP;
4504
4505 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004506 if (TmpReg == SReg) {
4507 TmpReg = getATReg(Inst.getLoc());
4508 if (!TmpReg)
4509 return true;
4510 }
4511
4512 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004513 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4514 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004515 return false;
4516 }
4517
4518 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004519 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004520 return false;
4521 }
4522
4523 return true;
4524 }
4525
4526 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004527 switch (Inst.getOpcode()) {
4528 default:
4529 llvm_unreachable("unexpected instruction opcode");
4530 case Mips::DROL:
4531 FirstShift = Mips::DSRLV;
4532 SecondShift = Mips::DSLLV;
4533 break;
4534 case Mips::DROR:
4535 FirstShift = Mips::DSLLV;
4536 SecondShift = Mips::DSRLV;
4537 break;
4538 }
4539
4540 ATReg = getATReg(Inst.getLoc());
4541 if (!ATReg)
4542 return true;
4543
Daniel Sandersa736b372016-04-29 13:33:12 +00004544 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4545 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4546 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4547 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004548
4549 return false;
4550 }
4551
4552 return true;
4553}
4554
4555bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004556 MCStreamer &Out,
4557 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004558 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004559 unsigned ATReg = Mips::NoRegister;
4560 unsigned DReg = Inst.getOperand(0).getReg();
4561 unsigned SReg = Inst.getOperand(1).getReg();
4562 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4563
4564 unsigned FirstShift = Mips::NOP;
4565 unsigned SecondShift = Mips::NOP;
4566
4567 MCInst TmpInst;
4568
4569 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004570 unsigned FinalOpcode = Mips::NOP;
4571 if (ImmValue == 0)
4572 FinalOpcode = Mips::DROTR;
4573 else if (ImmValue % 32 == 0)
4574 FinalOpcode = Mips::DROTR32;
4575 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4576 if (Inst.getOpcode() == Mips::DROLImm)
4577 FinalOpcode = Mips::DROTR32;
4578 else
4579 FinalOpcode = Mips::DROTR;
4580 } else if (ImmValue >= 33) {
4581 if (Inst.getOpcode() == Mips::DROLImm)
4582 FinalOpcode = Mips::DROTR;
4583 else
4584 FinalOpcode = Mips::DROTR32;
4585 }
4586
4587 uint64_t ShiftValue = ImmValue % 32;
4588 if (Inst.getOpcode() == Mips::DROLImm)
4589 ShiftValue = (32 - ImmValue % 32) % 32;
4590
Daniel Sandersa736b372016-04-29 13:33:12 +00004591 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004592
4593 return false;
4594 }
4595
4596 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004597 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004598 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004599 return false;
4600 }
4601
4602 switch (Inst.getOpcode()) {
4603 default:
4604 llvm_unreachable("unexpected instruction opcode");
4605 case Mips::DROLImm:
4606 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4607 FirstShift = Mips::DSLL;
4608 SecondShift = Mips::DSRL32;
4609 }
4610 if (ImmValue == 32) {
4611 FirstShift = Mips::DSLL32;
4612 SecondShift = Mips::DSRL32;
4613 }
4614 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4615 FirstShift = Mips::DSLL32;
4616 SecondShift = Mips::DSRL;
4617 }
4618 break;
4619 case Mips::DRORImm:
4620 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4621 FirstShift = Mips::DSRL;
4622 SecondShift = Mips::DSLL32;
4623 }
4624 if (ImmValue == 32) {
4625 FirstShift = Mips::DSRL32;
4626 SecondShift = Mips::DSLL32;
4627 }
4628 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4629 FirstShift = Mips::DSRL32;
4630 SecondShift = Mips::DSLL;
4631 }
4632 break;
4633 }
4634
4635 ATReg = getATReg(Inst.getLoc());
4636 if (!ATReg)
4637 return true;
4638
Daniel Sandersa736b372016-04-29 13:33:12 +00004639 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4640 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4641 Inst.getLoc(), STI);
4642 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004643
4644 return false;
4645 }
4646
4647 return true;
4648}
4649
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004650bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4651 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004652 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004653 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4654 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4655
Daniel Sandersa736b372016-04-29 13:33:12 +00004656 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004657 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004658 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004659 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004660 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4661 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004662
4663 return false;
4664}
4665
Simon Dardis3c82a642017-02-08 16:25:05 +00004666bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4667 const MCSubtargetInfo *STI) {
4668 MipsTargetStreamer &TOut = getTargetStreamer();
4669 unsigned ATReg = Mips::NoRegister;
4670 unsigned DstReg = Inst.getOperand(0).getReg();
4671 unsigned SrcReg = Inst.getOperand(1).getReg();
4672 int32_t ImmValue = Inst.getOperand(2).getImm();
4673
4674 ATReg = getATReg(IDLoc);
4675 if (!ATReg)
4676 return true;
4677
4678 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4679
4680 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4681 SrcReg, ATReg, IDLoc, STI);
4682
4683 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4684
4685 return false;
4686}
4687
4688bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4689 const MCSubtargetInfo *STI) {
4690 MipsTargetStreamer &TOut = getTargetStreamer();
4691 unsigned ATReg = Mips::NoRegister;
4692 unsigned DstReg = Inst.getOperand(0).getReg();
4693 unsigned SrcReg = Inst.getOperand(1).getReg();
4694 unsigned TmpReg = Inst.getOperand(2).getReg();
4695
4696 ATReg = getATReg(Inst.getLoc());
4697 if (!ATReg)
4698 return true;
4699
4700 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4701 SrcReg, TmpReg, IDLoc, STI);
4702
4703 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4704
4705 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4706 DstReg, DstReg, 0x1F, IDLoc, STI);
4707
4708 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4709
4710 if (useTraps()) {
4711 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4712 } else {
4713 MCContext & Context = TOut.getStreamer().getContext();
4714 MCSymbol * BrTarget = Context.createTempSymbol();
4715 MCOperand LabelOp =
4716 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4717
4718 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4719 if (AssemblerOptions.back()->isReorder())
4720 TOut.emitNop(IDLoc, STI);
4721 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4722
4723 TOut.getStreamer().EmitLabel(BrTarget);
4724 }
4725 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4726
4727 return false;
4728}
4729
4730bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4731 const MCSubtargetInfo *STI) {
4732 MipsTargetStreamer &TOut = getTargetStreamer();
4733 unsigned ATReg = Mips::NoRegister;
4734 unsigned DstReg = Inst.getOperand(0).getReg();
4735 unsigned SrcReg = Inst.getOperand(1).getReg();
4736 unsigned TmpReg = Inst.getOperand(2).getReg();
4737
4738 ATReg = getATReg(IDLoc);
4739 if (!ATReg)
4740 return true;
4741
4742 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4743 SrcReg, TmpReg, IDLoc, STI);
4744
4745 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4746 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4747 if (useTraps()) {
4748 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4749 } else {
4750 MCContext & Context = TOut.getStreamer().getContext();
4751 MCSymbol * BrTarget = Context.createTempSymbol();
4752 MCOperand LabelOp =
4753 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4754
4755 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4756 if (AssemblerOptions.back()->isReorder())
4757 TOut.emitNop(IDLoc, STI);
4758 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4759
4760 TOut.getStreamer().EmitLabel(BrTarget);
4761 }
4762
4763 return false;
4764}
4765
4766bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4767 const MCSubtargetInfo *STI) {
4768 MipsTargetStreamer &TOut = getTargetStreamer();
4769 unsigned DstReg = Inst.getOperand(0).getReg();
4770 unsigned SrcReg = Inst.getOperand(1).getReg();
4771 unsigned TmpReg = Inst.getOperand(2).getReg();
4772
4773 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4774 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4775
4776 return false;
4777}
4778
Simon Dardisaff4d142016-10-18 14:28:00 +00004779// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4780// lw $<reg+1>>, offset+4($reg2)'
4781// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4782// sw $<reg+1>>, offset+4($reg2)'
4783// for O32.
4784bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4785 MCStreamer &Out,
4786 const MCSubtargetInfo *STI,
4787 bool IsLoad) {
4788 if (!isABI_O32())
4789 return true;
4790
4791 warnIfNoMacro(IDLoc);
4792
4793 MipsTargetStreamer &TOut = getTargetStreamer();
4794 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4795 unsigned FirstReg = Inst.getOperand(0).getReg();
4796 unsigned SecondReg = nextReg(FirstReg);
4797 unsigned BaseReg = Inst.getOperand(1).getReg();
4798 if (!SecondReg)
4799 return true;
4800
4801 warnIfRegIndexIsAT(FirstReg, IDLoc);
4802
4803 assert(Inst.getOperand(2).isImm() &&
4804 "Offset for load macro is not immediate!");
4805
4806 MCOperand &FirstOffset = Inst.getOperand(2);
4807 signed NextOffset = FirstOffset.getImm() + 4;
4808 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4809
4810 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4811 return true;
4812
4813 // For loads, clobber the base register with the second load instead of the
4814 // first if the BaseReg == FirstReg.
4815 if (FirstReg != BaseReg || !IsLoad) {
4816 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4817 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4818 } else {
4819 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4820 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4821 }
4822
4823 return false;
4824}
4825
Simon Dardis43115a12016-11-21 20:30:41 +00004826bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4827 const MCSubtargetInfo *STI) {
4828
4829 warnIfNoMacro(IDLoc);
4830 MipsTargetStreamer &TOut = getTargetStreamer();
4831
4832 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4833 Inst.getOperand(2).getReg() != Mips::ZERO) {
4834 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4835 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4836 IDLoc, STI);
4837 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4838 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4839 return false;
4840 }
4841
4842 unsigned Reg = 0;
4843 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4844 Reg = Inst.getOperand(2).getReg();
4845 } else {
4846 Reg = Inst.getOperand(1).getReg();
4847 }
4848 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4849 return false;
4850}
4851
4852bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4853 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004854 warnIfNoMacro(IDLoc);
4855 MipsTargetStreamer &TOut = getTargetStreamer();
4856
4857 unsigned Opc;
4858 int64_t Imm = Inst.getOperand(2).getImm();
4859 unsigned Reg = Inst.getOperand(1).getReg();
4860
4861 if (Imm == 0) {
4862 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4863 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4864 return false;
4865 } else {
4866
4867 if (Reg == Mips::ZERO) {
4868 Warning(IDLoc, "comparison is always false");
4869 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4870 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4871 return false;
4872 }
4873
4874 if (Imm > -0x8000 && Imm < 0) {
4875 Imm = -Imm;
4876 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4877 } else {
4878 Opc = Mips::XORi;
4879 }
4880 }
4881 if (!isUInt<16>(Imm)) {
4882 unsigned ATReg = getATReg(IDLoc);
4883 if (!ATReg)
4884 return true;
4885
4886 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4887 Out, STI))
4888 return true;
4889
4890 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4891 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4892 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4893 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4894 return false;
4895 }
4896
4897 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4898 Imm, IDLoc, STI);
4899 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4900 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4901 return false;
4902}
4903
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004904// Map the DSP accumulator and control register to the corresponding gpr
4905// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4906// do not map the DSP registers contigously to gpr registers.
4907static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4908 switch (Inst.getOpcode()) {
4909 case Mips::MFTLO:
4910 case Mips::MTTLO:
4911 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4912 case Mips::AC0:
4913 return Mips::ZERO;
4914 case Mips::AC1:
4915 return Mips::A0;
4916 case Mips::AC2:
4917 return Mips::T0;
4918 case Mips::AC3:
4919 return Mips::T4;
4920 default:
4921 llvm_unreachable("Unknown register for 'mttr' alias!");
4922 }
4923 case Mips::MFTHI:
4924 case Mips::MTTHI:
4925 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4926 case Mips::AC0:
4927 return Mips::AT;
4928 case Mips::AC1:
4929 return Mips::A1;
4930 case Mips::AC2:
4931 return Mips::T1;
4932 case Mips::AC3:
4933 return Mips::T5;
4934 default:
4935 llvm_unreachable("Unknown register for 'mttr' alias!");
4936 }
4937 case Mips::MFTACX:
4938 case Mips::MTTACX:
4939 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4940 case Mips::AC0:
4941 return Mips::V0;
4942 case Mips::AC1:
4943 return Mips::A2;
4944 case Mips::AC2:
4945 return Mips::T2;
4946 case Mips::AC3:
4947 return Mips::T6;
4948 default:
4949 llvm_unreachable("Unknown register for 'mttr' alias!");
4950 }
4951 case Mips::MFTDSP:
4952 case Mips::MTTDSP:
4953 return Mips::S0;
4954 default:
4955 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4956 }
4957}
4958
4959// Map the floating point register operand to the corresponding register
4960// operand.
4961static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4962 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4963 case Mips::F0: return Mips::ZERO;
4964 case Mips::F1: return Mips::AT;
4965 case Mips::F2: return Mips::V0;
4966 case Mips::F3: return Mips::V1;
4967 case Mips::F4: return Mips::A0;
4968 case Mips::F5: return Mips::A1;
4969 case Mips::F6: return Mips::A2;
4970 case Mips::F7: return Mips::A3;
4971 case Mips::F8: return Mips::T0;
4972 case Mips::F9: return Mips::T1;
4973 case Mips::F10: return Mips::T2;
4974 case Mips::F11: return Mips::T3;
4975 case Mips::F12: return Mips::T4;
4976 case Mips::F13: return Mips::T5;
4977 case Mips::F14: return Mips::T6;
4978 case Mips::F15: return Mips::T7;
4979 case Mips::F16: return Mips::S0;
4980 case Mips::F17: return Mips::S1;
4981 case Mips::F18: return Mips::S2;
4982 case Mips::F19: return Mips::S3;
4983 case Mips::F20: return Mips::S4;
4984 case Mips::F21: return Mips::S5;
4985 case Mips::F22: return Mips::S6;
4986 case Mips::F23: return Mips::S7;
4987 case Mips::F24: return Mips::T8;
4988 case Mips::F25: return Mips::T9;
4989 case Mips::F26: return Mips::K0;
4990 case Mips::F27: return Mips::K1;
4991 case Mips::F28: return Mips::GP;
4992 case Mips::F29: return Mips::SP;
4993 case Mips::F30: return Mips::FP;
4994 case Mips::F31: return Mips::RA;
4995 default: llvm_unreachable("Unknown register for mttc1 alias!");
4996 }
4997}
4998
4999// Map the coprocessor operand the corresponding gpr register operand.
5000static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5001 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5002 case Mips::COP00: return Mips::ZERO;
5003 case Mips::COP01: return Mips::AT;
5004 case Mips::COP02: return Mips::V0;
5005 case Mips::COP03: return Mips::V1;
5006 case Mips::COP04: return Mips::A0;
5007 case Mips::COP05: return Mips::A1;
5008 case Mips::COP06: return Mips::A2;
5009 case Mips::COP07: return Mips::A3;
5010 case Mips::COP08: return Mips::T0;
5011 case Mips::COP09: return Mips::T1;
5012 case Mips::COP010: return Mips::T2;
5013 case Mips::COP011: return Mips::T3;
5014 case Mips::COP012: return Mips::T4;
5015 case Mips::COP013: return Mips::T5;
5016 case Mips::COP014: return Mips::T6;
5017 case Mips::COP015: return Mips::T7;
5018 case Mips::COP016: return Mips::S0;
5019 case Mips::COP017: return Mips::S1;
5020 case Mips::COP018: return Mips::S2;
5021 case Mips::COP019: return Mips::S3;
5022 case Mips::COP020: return Mips::S4;
5023 case Mips::COP021: return Mips::S5;
5024 case Mips::COP022: return Mips::S6;
5025 case Mips::COP023: return Mips::S7;
5026 case Mips::COP024: return Mips::T8;
5027 case Mips::COP025: return Mips::T9;
5028 case Mips::COP026: return Mips::K0;
5029 case Mips::COP027: return Mips::K1;
5030 case Mips::COP028: return Mips::GP;
5031 case Mips::COP029: return Mips::SP;
5032 case Mips::COP030: return Mips::FP;
5033 case Mips::COP031: return Mips::RA;
5034 default: llvm_unreachable("Unknown register for mttc0 alias!");
5035 }
5036}
5037
5038/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5039/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5040bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5041 const MCSubtargetInfo *STI) {
5042 MipsTargetStreamer &TOut = getTargetStreamer();
5043 unsigned rd = 0;
5044 unsigned u = 1;
5045 unsigned sel = 0;
5046 unsigned h = 0;
5047 bool IsMFTR = false;
5048 switch (Inst.getOpcode()) {
5049 case Mips::MFTC0:
5050 IsMFTR = true;
5051 LLVM_FALLTHROUGH;
5052 case Mips::MTTC0:
5053 u = 0;
5054 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5055 sel = Inst.getOperand(2).getImm();
5056 break;
5057 case Mips::MFTGPR:
5058 IsMFTR = true;
5059 LLVM_FALLTHROUGH;
5060 case Mips::MTTGPR:
5061 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5062 break;
5063 case Mips::MFTLO:
5064 case Mips::MFTHI:
5065 case Mips::MFTACX:
5066 case Mips::MFTDSP:
5067 IsMFTR = true;
5068 LLVM_FALLTHROUGH;
5069 case Mips::MTTLO:
5070 case Mips::MTTHI:
5071 case Mips::MTTACX:
5072 case Mips::MTTDSP:
5073 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5074 sel = 1;
5075 break;
5076 case Mips::MFTHC1:
5077 h = 1;
5078 LLVM_FALLTHROUGH;
5079 case Mips::MFTC1:
5080 IsMFTR = true;
5081 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5082 sel = 2;
5083 break;
5084 case Mips::MTTHC1:
5085 h = 1;
5086 LLVM_FALLTHROUGH;
5087 case Mips::MTTC1:
5088 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5089 sel = 2;
5090 break;
5091 case Mips::CFTC1:
5092 IsMFTR = true;
5093 LLVM_FALLTHROUGH;
5094 case Mips::CTTC1:
5095 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5096 sel = 3;
5097 break;
5098 }
5099 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5100 unsigned Op1 =
5101 IsMFTR ? rd
5102 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5103 : Inst.getOperand(0).getReg());
5104
5105 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5106 STI);
5107 return false;
5108}
5109
Daniel Sandersc5537422016-07-27 13:49:44 +00005110unsigned
5111MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5112 const OperandVector &Operands) {
5113 switch (Inst.getOpcode()) {
5114 default:
5115 return Match_Success;
5116 case Mips::DATI:
5117 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005118 if (static_cast<MipsOperand &>(*Operands[1])
5119 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5120 return Match_Success;
5121 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005122 }
5123}
Simon Dardis730fdb72017-01-16 13:55:58 +00005124
Matheus Almeida595fcab2014-06-11 15:05:56 +00005125unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005126 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005127 // As described by the MIPSR6 spec, daui must not use the zero operand for
5128 // its source operand.
5129 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005130 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5131 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5132 return Match_RequiresNoZeroRegister;
5133 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005134 // As described by the Mips32r2 spec, the registers Rd and Rs for
5135 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005136 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005137 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005138 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005139 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005140 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005141 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005142 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5143 return Match_RequiresDifferentSrcAndDst;
5144 return Match_Success;
5145 case Mips::LWP_MM:
5146 case Mips::LWP_MMR6:
5147 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5148 return Match_RequiresDifferentSrcAndDst;
5149 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005150 case Mips::SYNC:
5151 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5152 return Match_NonZeroOperandForSync;
5153 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005154 // As described the MIPSR6 spec, the compact branches that compare registers
5155 // must:
5156 // a) Not use the zero register.
5157 // b) Not use the same register twice.
5158 // c) rs < rt for bnec, beqc.
5159 // NB: For this case, the encoding will swap the operands as their
5160 // ordering doesn't matter. GAS performs this transformation too.
5161 // Hence, that constraint does not have to be enforced.
5162 //
5163 // The compact branches that branch iff the signed addition of two registers
5164 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5165 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005166 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5167 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5168 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5169 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5170 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5171 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005172 case Mips::BLEZC64:
5173 case Mips::BGEZC64:
5174 case Mips::BGTZC64:
5175 case Mips::BLTZC64:
5176 case Mips::BEQZC64:
5177 case Mips::BNEZC64:
5178 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5179 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005180 return Match_RequiresNoZeroRegister;
5181 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005182 case Mips::BGEC: case Mips::BGEC_MMR6:
5183 case Mips::BLTC: case Mips::BLTC_MMR6:
5184 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5185 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5186 case Mips::BEQC: case Mips::BEQC_MMR6:
5187 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005188 case Mips::BGEC64:
5189 case Mips::BLTC64:
5190 case Mips::BGEUC64:
5191 case Mips::BLTUC64:
5192 case Mips::BEQC64:
5193 case Mips::BNEC64:
5194 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5195 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005196 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005197 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5198 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005199 return Match_RequiresNoZeroRegister;
5200 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5201 return Match_RequiresDifferentOperands;
5202 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005203 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005204 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5205 "Operands must be immediates for dins!");
5206 const signed Pos = Inst.getOperand(2).getImm();
5207 const signed Size = Inst.getOperand(3).getImm();
5208 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5209 return Match_RequiresPosSizeRange0_32;
5210 return Match_Success;
5211 }
5212 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005213 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005214 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5215 "Operands must be immediates for dinsm/dinsu!");
5216 const signed Pos = Inst.getOperand(2).getImm();
5217 const signed Size = Inst.getOperand(3).getImm();
5218 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5219 return Match_RequiresPosSizeRange33_64;
5220 return Match_Success;
5221 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005222 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005223 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5224 "Operands must be immediates for DEXTM!");
5225 const signed Pos = Inst.getOperand(2).getImm();
5226 const signed Size = Inst.getOperand(3).getImm();
5227 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5228 return Match_RequiresPosSizeUImm6;
5229 return Match_Success;
5230 }
5231 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005232 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005233 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5234 "Operands must be immediates for dextm/dextu!");
5235 const signed Pos = Inst.getOperand(2).getImm();
5236 const signed Size = Inst.getOperand(3).getImm();
5237 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5238 return Match_RequiresPosSizeRange33_64;
5239 return Match_Success;
5240 }
Simon Dardisb60833c2016-05-31 17:34:42 +00005241 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005242
5243 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5244 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5245 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5246 return Match_NoFCCRegisterForCurrentISA;
5247
5248 return Match_Success;
5249
Matheus Almeida595fcab2014-06-11 15:05:56 +00005250}
5251
Daniel Sanders52da7af2015-11-06 12:11:03 +00005252static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5253 uint64_t ErrorInfo) {
5254 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5255 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5256 if (ErrorLoc == SMLoc())
5257 return Loc;
5258 return ErrorLoc;
5259 }
5260 return Loc;
5261}
5262
David Blaikie960ea3f2014-06-08 16:18:35 +00005263bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5264 OperandVector &Operands,
5265 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005266 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005267 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005268 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005269 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005270 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005271
5272 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005273 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005274 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005275 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005276 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005277 case Match_MissingFeature:
5278 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5279 return true;
5280 case Match_InvalidOperand: {
5281 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005282 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005283 if (ErrorInfo >= Operands.size())
5284 return Error(IDLoc, "too few operands for instruction");
5285
Daniel Sanders52da7af2015-11-06 12:11:03 +00005286 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005287 if (ErrorLoc == SMLoc())
5288 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005289 }
5290
5291 return Error(ErrorLoc, "invalid operand for instruction");
5292 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005293 case Match_NonZeroOperandForSync:
5294 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005295 case Match_MnemonicFail:
5296 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005297 case Match_RequiresDifferentSrcAndDst:
5298 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005299 case Match_RequiresDifferentOperands:
5300 return Error(IDLoc, "registers must be different");
5301 case Match_RequiresNoZeroRegister:
5302 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005303 case Match_RequiresSameSrcAndDst:
5304 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005305 case Match_NoFCCRegisterForCurrentISA:
5306 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5307 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005308 case Match_Immz:
5309 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005310 case Match_UImm1_0:
5311 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5312 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005313 case Match_UImm2_0:
5314 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5315 "expected 2-bit unsigned immediate");
5316 case Match_UImm2_1:
5317 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5318 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005319 case Match_UImm3_0:
5320 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5321 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005322 case Match_UImm4_0:
5323 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5324 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005325 case Match_SImm4_0:
5326 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5327 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005328 case Match_UImm5_0:
5329 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5330 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005331 case Match_SImm5_0:
5332 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5333 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005334 case Match_UImm5_1:
5335 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5336 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005337 case Match_UImm5_32:
5338 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5339 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005340 case Match_UImm5_33:
5341 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5342 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005343 case Match_UImm5_0_Report_UImm6:
5344 // This is used on UImm5 operands that have a corresponding UImm5_32
5345 // operand to avoid confusing the user.
5346 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5347 "expected 6-bit unsigned immediate");
5348 case Match_UImm5_Lsl2:
5349 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5350 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005351 case Match_UImmRange2_64:
5352 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5353 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005354 case Match_UImm6_0:
5355 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5356 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005357 case Match_UImm6_Lsl2:
5358 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5359 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005360 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005361 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5362 "expected 6-bit signed immediate");
5363 case Match_UImm7_0:
5364 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5365 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005366 case Match_UImm7_N1:
5367 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5368 "expected immediate in range -1 .. 126");
5369 case Match_SImm7_Lsl2:
5370 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5371 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005372 case Match_UImm8_0:
5373 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5374 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005375 case Match_UImm10_0:
5376 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5377 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005378 case Match_SImm10_0:
5379 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5380 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005381 case Match_SImm11_0:
5382 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5383 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005384 case Match_UImm16:
5385 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005386 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5388 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005389 case Match_SImm16:
5390 case Match_SImm16_Relaxed:
5391 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5392 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005393 case Match_SImm19_Lsl2:
5394 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5395 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005396 case Match_UImm20_0:
5397 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5398 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005399 case Match_UImm26_0:
5400 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5401 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005402 case Match_SImm32:
5403 case Match_SImm32_Relaxed:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005406 case Match_UImm32_Coerced:
5407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5408 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005409 case Match_MemSImm9:
5410 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5411 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005412 case Match_MemSImm10:
5413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5414 "expected memory with 10-bit signed offset");
5415 case Match_MemSImm10Lsl1:
5416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5417 "expected memory with 11-bit signed offset and multiple of 2");
5418 case Match_MemSImm10Lsl2:
5419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5420 "expected memory with 12-bit signed offset and multiple of 4");
5421 case Match_MemSImm10Lsl3:
5422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5423 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005424 case Match_MemSImm11:
5425 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5426 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005427 case Match_MemSImm12:
5428 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5429 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005430 case Match_MemSImm16:
5431 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5432 "expected memory with 16-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005433 case Match_RequiresPosSizeRange0_32: {
5434 SMLoc ErrorStart = Operands[3]->getStartLoc();
5435 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5436 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5437 SMRange(ErrorStart, ErrorEnd));
5438 }
Simon Dardis55e44672017-09-14 17:27:53 +00005439 case Match_RequiresPosSizeUImm6: {
5440 SMLoc ErrorStart = Operands[3]->getStartLoc();
5441 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5442 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5443 SMRange(ErrorStart, ErrorEnd));
5444 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005445 case Match_RequiresPosSizeRange33_64: {
5446 SMLoc ErrorStart = Operands[3]->getStartLoc();
5447 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5448 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5449 SMRange(ErrorStart, ErrorEnd));
5450 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005451 }
Craig Topper589ceee2015-01-03 08:16:34 +00005452
5453 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005454}
5455
Toma Tabacud9d344b2015-04-27 14:05:04 +00005456void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5457 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5458 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5459 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005460}
5461
Toma Tabacu81496c12015-05-20 08:54:45 +00005462void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5463 if (!AssemblerOptions.back()->isMacro())
5464 Warning(Loc, "macro instruction expanded into multiple instructions");
5465}
5466
Daniel Sandersef638fe2014-10-03 15:37:37 +00005467void
5468MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5469 SMRange Range, bool ShowColors) {
5470 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005471 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005472 ShowColors);
5473}
5474
Jack Carter1ac53222013-02-20 23:11:17 +00005475int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005476 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005477
Vladimir Medic4c299852013-11-06 11:27:05 +00005478 CC = StringSwitch<unsigned>(Name)
5479 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005480 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005481 .Case("a0", 4)
5482 .Case("a1", 5)
5483 .Case("a2", 6)
5484 .Case("a3", 7)
5485 .Case("v0", 2)
5486 .Case("v1", 3)
5487 .Case("s0", 16)
5488 .Case("s1", 17)
5489 .Case("s2", 18)
5490 .Case("s3", 19)
5491 .Case("s4", 20)
5492 .Case("s5", 21)
5493 .Case("s6", 22)
5494 .Case("s7", 23)
5495 .Case("k0", 26)
5496 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005497 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005498 .Case("sp", 29)
5499 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005500 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005501 .Case("ra", 31)
5502 .Case("t0", 8)
5503 .Case("t1", 9)
5504 .Case("t2", 10)
5505 .Case("t3", 11)
5506 .Case("t4", 12)
5507 .Case("t5", 13)
5508 .Case("t6", 14)
5509 .Case("t7", 15)
5510 .Case("t8", 24)
5511 .Case("t9", 25)
5512 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005513
Toma Tabacufda445c2014-09-15 15:33:01 +00005514 if (!(isABI_N32() || isABI_N64()))
5515 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005516
Daniel Sandersef638fe2014-10-03 15:37:37 +00005517 if (12 <= CC && CC <= 15) {
5518 // Name is one of t4-t7
5519 AsmToken RegTok = getLexer().peekTok();
5520 SMRange RegRange = RegTok.getLocRange();
5521
5522 StringRef FixedName = StringSwitch<StringRef>(Name)
5523 .Case("t4", "t0")
5524 .Case("t5", "t1")
5525 .Case("t6", "t2")
5526 .Case("t7", "t3")
5527 .Default("");
5528 assert(FixedName != "" && "Register name is not one of t4-t7.");
5529
5530 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5531 "Did you mean $" + FixedName + "?", RegRange);
5532 }
5533
Toma Tabacufda445c2014-09-15 15:33:01 +00005534 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5535 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5536 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5537 if (8 <= CC && CC <= 11)
5538 CC += 4;
5539
5540 if (CC == -1)
5541 CC = StringSwitch<unsigned>(Name)
5542 .Case("a4", 8)
5543 .Case("a5", 9)
5544 .Case("a6", 10)
5545 .Case("a7", 11)
5546 .Case("kt0", 26)
5547 .Case("kt1", 27)
5548 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005549
5550 return CC;
5551}
Jack Carterd0bd6422013-04-18 00:41:53 +00005552
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005553int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5554 int CC;
5555
5556 CC = StringSwitch<unsigned>(Name)
5557 .Case("hwr_cpunum", 0)
5558 .Case("hwr_synci_step", 1)
5559 .Case("hwr_cc", 2)
5560 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005561 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005562 .Default(-1);
5563
5564 return CC;
5565}
5566
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005567int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005568 if (Name[0] == 'f') {
5569 StringRef NumString = Name.substr(1);
5570 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005571 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005572 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005573 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005574 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005575 return IntVal;
5576 }
5577 return -1;
5578}
Jack Cartera63b16a2012-09-07 00:23:42 +00005579
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005580int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005581 if (Name.startswith("fcc")) {
5582 StringRef NumString = Name.substr(3);
5583 unsigned IntVal;
5584 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005585 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005586 if (IntVal > 7) // There are only 8 fcc registers.
5587 return -1;
5588 return IntVal;
5589 }
5590 return -1;
5591}
5592
5593int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005594 if (Name.startswith("ac")) {
5595 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005596 unsigned IntVal;
5597 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005598 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005599 if (IntVal > 3) // There are only 3 acc registers.
5600 return -1;
5601 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005602 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005603 return -1;
5604}
Jack Carterd0bd6422013-04-18 00:41:53 +00005605
Jack Carter5dc8ac92013-09-25 23:50:44 +00005606int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5607 unsigned IntVal;
5608
5609 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5610 return -1;
5611
5612 if (IntVal > 31)
5613 return -1;
5614
5615 return IntVal;
5616}
5617
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005618int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5619 int CC;
5620
5621 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005622 .Case("msair", 0)
5623 .Case("msacsr", 1)
5624 .Case("msaaccess", 2)
5625 .Case("msasave", 3)
5626 .Case("msamodify", 4)
5627 .Case("msarequest", 5)
5628 .Case("msamap", 6)
5629 .Case("msaunmap", 7)
5630 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005631
5632 return CC;
5633}
5634
Simon Dardis3aa8a902017-02-06 12:43:46 +00005635bool MipsAsmParser::canUseATReg() {
5636 return AssemblerOptions.back()->getATRegIndex() != 0;
5637}
5638
Toma Tabacu89a712b2015-04-15 10:48:56 +00005639unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005640 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005641 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005642 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005643 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005644 return 0;
5645 }
5646 unsigned AT = getReg(
5647 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005648 return AT;
5649}
Jack Carter0b744b32012-10-04 02:29:46 +00005650
Jack Carterd0bd6422013-04-18 00:41:53 +00005651unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005652 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005653}
5654
Toma Tabacu13964452014-09-04 13:23:44 +00005655bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005656 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005657 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005658
Jack Carter30a59822012-10-04 04:03:53 +00005659 // Check if the current operand has a custom associated parser, if so, try to
5660 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005661 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5662 if (ResTy == MatchOperand_Success)
5663 return false;
5664 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5665 // there was a match, but an error occurred, in which case, just return that
5666 // the operand parsing failed.
5667 if (ResTy == MatchOperand_ParseFail)
5668 return true;
5669
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005670 DEBUG(dbgs() << ".. Generic Parser\n");
5671
Jack Carterb4dbc172012-09-05 23:34:03 +00005672 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005673 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005674 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005675 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005676
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005677 // Almost all registers have been parsed by custom parsers. There is only
5678 // one exception to this. $zero (and it's alias $0) will reach this point
5679 // for div, divu, and similar instructions because it is not an operand
5680 // to the instruction definition but an explicit register. Special case
5681 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005682 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005683 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005684
Jack Carterd0bd6422013-04-18 00:41:53 +00005685 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005686 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005687 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005688 return true;
5689
Jack Carter873c7242013-01-12 01:03:14 +00005690 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005691 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005692 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005693 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005694 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005695
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005696 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005697 return false;
5698 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005699 default: {
5700 DEBUG(dbgs() << ".. generic integer expression\n");
5701
5702 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005703 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005704 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005705 return true;
5706
Jack Carter873c7242013-01-12 01:03:14 +00005707 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5708
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005709 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005710 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005711 }
Jack Carter0b744b32012-10-04 02:29:46 +00005712 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005713 return true;
5714}
5715
Jack Carterb5cf5902013-04-17 00:18:04 +00005716bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005717 switch (Expr->getKind()) {
5718 case MCExpr::Constant:
5719 return true;
5720 case MCExpr::SymbolRef:
5721 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005722 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005723 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005724 if (!isEvaluated(BE->getLHS()))
5725 return false;
5726 return isEvaluated(BE->getRHS());
5727 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005728 case MCExpr::Unary:
5729 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005730 case MCExpr::Target:
5731 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005732 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005733 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005734}
Jack Carterd0bd6422013-04-18 00:41:53 +00005735
Jack Carterb4dbc172012-09-05 23:34:03 +00005736bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5737 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005738 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005739 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005740 if (ResTy == MatchOperand_Success) {
5741 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005742 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005743 StartLoc = Operand.getStartLoc();
5744 EndLoc = Operand.getEndLoc();
5745
5746 // AFAIK, we only support numeric registers and named GPR's in CFI
5747 // directives.
5748 // Don't worry about eating tokens before failing. Using an unrecognised
5749 // register is a parse error.
5750 if (Operand.isGPRAsmReg()) {
5751 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005752 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005753 }
5754
5755 return (RegNo == (unsigned)-1);
5756 }
5757
5758 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005759 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005760}
5761
Jack Carterb5cf5902013-04-17 00:18:04 +00005762bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005763 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005764
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005765 if (isParenExpr)
5766 return getParser().parseParenExprOfDepth(0, Res, S);
5767 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005768}
5769
Alex Bradbury58eba092016-11-01 16:32:05 +00005770OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005771MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005772 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005773 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005774 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005775 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005776 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005777 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005778 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005779 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005780
Jack Carterb5cf5902013-04-17 00:18:04 +00005781 if (getLexer().getKind() == AsmToken::LParen) {
5782 Parser.Lex();
5783 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005784 }
5785
Jack Carterb5cf5902013-04-17 00:18:04 +00005786 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005787 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005788 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005789
Jack Carterd0bd6422013-04-18 00:41:53 +00005790 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005791 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005792 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005793 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005794 SMLoc E =
5795 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005796 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005797 return MatchOperand_Success;
5798 }
5799 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005800 SMLoc E =
5801 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005802
Jack Carterd0bd6422013-04-18 00:41:53 +00005803 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005804 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005805 auto Base = MipsOperand::createGPRReg(
5806 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005807 Operands.push_back(
5808 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005809 return MatchOperand_Success;
5810 }
Simon Dardis858915f2016-10-18 15:17:17 +00005811 MCBinaryExpr::Opcode Opcode;
5812 // GAS and LLVM treat comparison operators different. GAS will generate -1
5813 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5814 // highly unlikely to be found in a memory offset expression, we don't
5815 // handle them.
5816 switch (Tok.getKind()) {
5817 case AsmToken::Plus:
5818 Opcode = MCBinaryExpr::Add;
5819 Parser.Lex();
5820 break;
5821 case AsmToken::Minus:
5822 Opcode = MCBinaryExpr::Sub;
5823 Parser.Lex();
5824 break;
5825 case AsmToken::Star:
5826 Opcode = MCBinaryExpr::Mul;
5827 Parser.Lex();
5828 break;
5829 case AsmToken::Pipe:
5830 Opcode = MCBinaryExpr::Or;
5831 Parser.Lex();
5832 break;
5833 case AsmToken::Amp:
5834 Opcode = MCBinaryExpr::And;
5835 Parser.Lex();
5836 break;
5837 case AsmToken::LessLess:
5838 Opcode = MCBinaryExpr::Shl;
5839 Parser.Lex();
5840 break;
5841 case AsmToken::GreaterGreater:
5842 Opcode = MCBinaryExpr::LShr;
5843 Parser.Lex();
5844 break;
5845 case AsmToken::Caret:
5846 Opcode = MCBinaryExpr::Xor;
5847 Parser.Lex();
5848 break;
5849 case AsmToken::Slash:
5850 Opcode = MCBinaryExpr::Div;
5851 Parser.Lex();
5852 break;
5853 case AsmToken::Percent:
5854 Opcode = MCBinaryExpr::Mod;
5855 Parser.Lex();
5856 break;
5857 default:
5858 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5859 return MatchOperand_ParseFail;
5860 }
5861 const MCExpr * NextExpr;
5862 if (getParser().parseExpression(NextExpr))
5863 return MatchOperand_ParseFail;
5864 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005865 }
5866
Jack Carterd0bd6422013-04-18 00:41:53 +00005867 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005868 }
5869
Toma Tabacu13964452014-09-04 13:23:44 +00005870 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005871 if (Res != MatchOperand_Success)
5872 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005873
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005874 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005875 Error(Parser.getTok().getLoc(), "')' expected");
5876 return MatchOperand_ParseFail;
5877 }
5878
Jack Carter873c7242013-01-12 01:03:14 +00005879 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5880
Jack Carterd0bd6422013-04-18 00:41:53 +00005881 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005882
Craig Topper062a2ba2014-04-25 05:30:21 +00005883 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005884 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005885
Jack Carterd0bd6422013-04-18 00:41:53 +00005886 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005887 std::unique_ptr<MipsOperand> op(
5888 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005889 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005890 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005891 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005892 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005893 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5894 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005895 if (IdVal->evaluateAsAbsolute(Imm))
5896 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005897 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005898 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005899 getContext());
5900 }
5901
David Blaikie960ea3f2014-06-08 16:18:35 +00005902 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005903 return MatchOperand_Success;
5904}
5905
David Blaikie960ea3f2014-06-08 16:18:35 +00005906bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005907 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005908 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005909 if (Sym) {
5910 SMLoc S = Parser.getTok().getLoc();
5911 const MCExpr *Expr;
5912 if (Sym->isVariable())
5913 Expr = Sym->getVariableValue();
5914 else
5915 return false;
5916 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005917 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005918 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005919 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005920 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005921 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005922 if (ResTy == MatchOperand_Success) {
5923 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005924 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005925 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005926 llvm_unreachable("Should never ParseFail");
5927 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005928 }
Jack Carterd76b2372013-03-21 21:44:16 +00005929 }
5930 }
5931 return false;
5932}
Jack Carterd0bd6422013-04-18 00:41:53 +00005933
Alex Bradbury58eba092016-11-01 16:32:05 +00005934OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005935MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005936 StringRef Identifier,
5937 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005938 int Index = matchCPURegisterName(Identifier);
5939 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005940 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005941 Index, Identifier, getContext().getRegisterInfo(), S,
5942 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005943 return MatchOperand_Success;
5944 }
5945
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005946 Index = matchHWRegsRegisterName(Identifier);
5947 if (Index != -1) {
5948 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005949 Index, Identifier, getContext().getRegisterInfo(), S,
5950 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005951 return MatchOperand_Success;
5952 }
5953
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005954 Index = matchFPURegisterName(Identifier);
5955 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005956 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005957 Index, Identifier, getContext().getRegisterInfo(), S,
5958 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005959 return MatchOperand_Success;
5960 }
5961
5962 Index = matchFCCRegisterName(Identifier);
5963 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005964 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005965 Index, Identifier, getContext().getRegisterInfo(), S,
5966 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005967 return MatchOperand_Success;
5968 }
5969
5970 Index = matchACRegisterName(Identifier);
5971 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005972 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005973 Index, Identifier, getContext().getRegisterInfo(), S,
5974 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005975 return MatchOperand_Success;
5976 }
5977
5978 Index = matchMSA128RegisterName(Identifier);
5979 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005980 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005981 Index, Identifier, getContext().getRegisterInfo(), S,
5982 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005983 return MatchOperand_Success;
5984 }
5985
5986 Index = matchMSA128CtrlRegisterName(Identifier);
5987 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005988 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005989 Index, Identifier, getContext().getRegisterInfo(), S,
5990 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005991 return MatchOperand_Success;
5992 }
5993
5994 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005995}
5996
Alex Bradbury58eba092016-11-01 16:32:05 +00005997OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005998MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005999 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00006000 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006001
6002 if (Token.is(AsmToken::Identifier)) {
6003 DEBUG(dbgs() << ".. identifier\n");
6004 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006005 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006006 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006007 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006008 } else if (Token.is(AsmToken::Integer)) {
6009 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00006010 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006011 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
6012 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006013 return MatchOperand_Success;
6014 }
6015
6016 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
6017
6018 return MatchOperand_NoMatch;
6019}
6020
Alex Bradbury58eba092016-11-01 16:32:05 +00006021OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006022MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006023 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006024 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006025
6026 auto Token = Parser.getTok();
6027
6028 SMLoc S = Token.getLoc();
6029
6030 if (Token.isNot(AsmToken::Dollar)) {
6031 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
6032 if (Token.is(AsmToken::Identifier)) {
6033 if (searchSymbolAlias(Operands))
6034 return MatchOperand_Success;
6035 }
6036 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
6037 return MatchOperand_NoMatch;
6038 }
6039 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006040
Toma Tabacu13964452014-09-04 13:23:44 +00006041 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006042 if (ResTy == MatchOperand_Success) {
6043 Parser.Lex(); // $
6044 Parser.Lex(); // identifier
6045 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006046 return ResTy;
6047}
6048
Alex Bradbury58eba092016-11-01 16:32:05 +00006049OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006050MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006051 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006052 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006053
6054 SMLoc S = getLexer().getLoc();
6055
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006056 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006057 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006058 if (ResTy != MatchOperand_NoMatch)
6059 return ResTy;
6060
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006061 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006062 const MCExpr *Expr = nullptr;
6063 if (Parser.parseExpression(Expr)) {
6064 // We have no way of knowing if a symbol was consumed so we must ParseFail
6065 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006066 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006067 Operands.push_back(
6068 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006069 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006070}
6071
Alex Bradbury58eba092016-11-01 16:32:05 +00006072OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006073MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006074 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006075 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006076 // If the first token is '$' we may have register operand. We have to reject
6077 // cases where it is not a register. Complicating the matter is that
6078 // register names are not reserved across all ABIs.
6079 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006080 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006081 if (Parser.getTok().is(AsmToken::Dollar)) {
6082 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6083 ? MatchOperand_ParseFail
6084 : MatchOperand_NoMatch;
6085 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006086 if (getParser().parseExpression(IdVal))
6087 return MatchOperand_ParseFail;
6088 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006089 if (!MCE)
6090 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006091 int64_t Val = MCE->getValue();
6092 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6093 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006094 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006095 return MatchOperand_Success;
6096}
6097
Alex Bradbury58eba092016-11-01 16:32:05 +00006098OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006099MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6100 MCAsmParser &Parser = getParser();
6101 SmallVector<unsigned, 10> Regs;
6102 unsigned RegNo;
6103 unsigned PrevReg = Mips::NoRegister;
6104 bool RegRange = false;
6105 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6106
6107 if (Parser.getTok().isNot(AsmToken::Dollar))
6108 return MatchOperand_ParseFail;
6109
6110 SMLoc S = Parser.getTok().getLoc();
6111 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6112 SMLoc E = getLexer().getLoc();
6113 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6114 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6115 if (RegRange) {
6116 // Remove last register operand because registers from register range
6117 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006118 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6119 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006120 Regs.push_back(RegNo);
6121 } else {
6122 unsigned TmpReg = PrevReg + 1;
6123 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006124 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6125 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6126 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006127 Error(E, "invalid register operand");
6128 return MatchOperand_ParseFail;
6129 }
6130
6131 PrevReg = TmpReg;
6132 Regs.push_back(TmpReg++);
6133 }
6134 }
6135
6136 RegRange = false;
6137 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006138 if ((PrevReg == Mips::NoRegister) &&
6139 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6140 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006141 Error(E, "$16 or $31 expected");
6142 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006143 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6144 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6145 !isGP64bit()) ||
6146 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6147 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6148 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006149 Error(E, "invalid register operand");
6150 return MatchOperand_ParseFail;
6151 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006152 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6153 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6154 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006155 Error(E, "consecutive register numbers expected");
6156 return MatchOperand_ParseFail;
6157 }
6158
6159 Regs.push_back(RegNo);
6160 }
6161
6162 if (Parser.getTok().is(AsmToken::Minus))
6163 RegRange = true;
6164
6165 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6166 !Parser.getTok().isNot(AsmToken::Comma)) {
6167 Error(E, "',' or '-' expected");
6168 return MatchOperand_ParseFail;
6169 }
6170
6171 Lex(); // Consume comma or minus
6172 if (Parser.getTok().isNot(AsmToken::Dollar))
6173 break;
6174
6175 PrevReg = RegNo;
6176 }
6177
6178 SMLoc E = Parser.getTok().getLoc();
6179 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6180 parseMemOperand(Operands);
6181 return MatchOperand_Success;
6182}
6183
Alex Bradbury58eba092016-11-01 16:32:05 +00006184OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006185MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6186 MCAsmParser &Parser = getParser();
6187
6188 SMLoc S = Parser.getTok().getLoc();
6189 if (parseAnyRegister(Operands) != MatchOperand_Success)
6190 return MatchOperand_ParseFail;
6191
6192 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006193 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006194
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006195 Operands.pop_back();
6196 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006197 return MatchOperand_Success;
6198}
6199
Alex Bradbury58eba092016-11-01 16:32:05 +00006200OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006201MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6202 MCAsmParser &Parser = getParser();
6203 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6204 SmallVector<unsigned, 10> Regs;
6205
6206 if (Parser.getTok().isNot(AsmToken::Dollar))
6207 return MatchOperand_ParseFail;
6208
6209 SMLoc S = Parser.getTok().getLoc();
6210
6211 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6212 return MatchOperand_ParseFail;
6213
6214 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6215 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6216 Regs.push_back(RegNo);
6217
6218 SMLoc E = Parser.getTok().getLoc();
6219 if (Parser.getTok().isNot(AsmToken::Comma)) {
6220 Error(E, "',' expected");
6221 return MatchOperand_ParseFail;
6222 }
6223
6224 // Remove comma.
6225 Parser.Lex();
6226
6227 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6228 return MatchOperand_ParseFail;
6229
6230 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6231 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6232 Regs.push_back(RegNo);
6233
6234 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6235
6236 return MatchOperand_Success;
6237}
6238
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006239/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6240/// either this.
6241/// ::= '(', register, ')'
6242/// handle it before we iterate so we don't get tripped up by the lack of
6243/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006244bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006245 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006246 if (getLexer().is(AsmToken::LParen)) {
6247 Operands.push_back(
6248 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6249 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006250 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006251 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006252 return Error(Loc, "unexpected token in argument list");
6253 }
6254 if (Parser.getTok().isNot(AsmToken::RParen)) {
6255 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006256 return Error(Loc, "unexpected token, expected ')'");
6257 }
6258 Operands.push_back(
6259 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6260 Parser.Lex();
6261 }
6262 return false;
6263}
6264
6265/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6266/// either one of these.
6267/// ::= '[', register, ']'
6268/// ::= '[', integer, ']'
6269/// handle it before we iterate so we don't get tripped up by the lack of
6270/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006271bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006272 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006273 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006274 if (getLexer().is(AsmToken::LBrac)) {
6275 Operands.push_back(
6276 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6277 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006278 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006279 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006280 return Error(Loc, "unexpected token in argument list");
6281 }
6282 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6283 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006284 return Error(Loc, "unexpected token, expected ']'");
6285 }
6286 Operands.push_back(
6287 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6288 Parser.Lex();
6289 }
6290 return false;
6291}
6292
David Blaikie960ea3f2014-06-08 16:18:35 +00006293bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6294 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006295 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006296 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006297
6298 // We have reached first instruction, module directive are now forbidden.
6299 getTargetStreamer().forbidModuleDirective();
6300
Vladimir Medic74593e62013-07-17 15:00:42 +00006301 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006302 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006303 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006304 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006305 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006306 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006307
6308 // Read the remaining operands.
6309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6310 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006311 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006312 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006313 return Error(Loc, "unexpected token in argument list");
6314 }
Toma Tabacu13964452014-09-04 13:23:44 +00006315 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006316 return true;
6317 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006318
Jack Carterd0bd6422013-04-18 00:41:53 +00006319 while (getLexer().is(AsmToken::Comma)) {
6320 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006321 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006322 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006323 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006324 return Error(Loc, "unexpected token in argument list");
6325 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006326 // Parse bracket and parenthesis suffixes before we iterate
6327 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006328 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006329 return true;
6330 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006331 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006332 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006333 }
6334 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006335 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6336 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006337 return Error(Loc, "unexpected token in argument list");
6338 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006339 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006340 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006341}
6342
Nirav Dave996fc132016-05-05 14:15:46 +00006343// FIXME: Given that these have the same name, these should both be
6344// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006345bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006346 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006347 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006348}
6349
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006350bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006351 return Error(Loc, ErrorMsg);
6352}
6353
Jack Carter0b744b32012-10-04 02:29:46 +00006354bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006355 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006356 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006357
6358 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006359 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006360
6361 Parser.Lex(); // Eat "noat".
6362
Jack Carterd0bd6422013-04-18 00:41:53 +00006363 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006364 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006365 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006366 return false;
6367 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006368
6369 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006370 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006371 return false;
6372}
Jack Carterd0bd6422013-04-18 00:41:53 +00006373
Jack Carter0b744b32012-10-04 02:29:46 +00006374bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006375 // Line can be: ".set at", which sets $at to $1
6376 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006377 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006378 Parser.Lex(); // Eat "at".
6379
Jack Carter0b744b32012-10-04 02:29:46 +00006380 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006381 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006382 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006383
6384 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006385 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006386 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006387 }
6388
6389 if (getLexer().isNot(AsmToken::Equal)) {
6390 reportParseError("unexpected token, expected equals sign");
6391 return false;
6392 }
6393 Parser.Lex(); // Eat "=".
6394
6395 if (getLexer().isNot(AsmToken::Dollar)) {
6396 if (getLexer().is(AsmToken::EndOfStatement)) {
6397 reportParseError("no register specified");
6398 return false;
6399 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006400 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006401 return false;
6402 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006403 }
6404 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006405
Toma Tabacu16a74492015-02-13 10:30:57 +00006406 // Find out what "reg" is.
6407 unsigned AtRegNo;
6408 const AsmToken &Reg = Parser.getTok();
6409 if (Reg.is(AsmToken::Identifier)) {
6410 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6411 } else if (Reg.is(AsmToken::Integer)) {
6412 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006413 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006414 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006415 return false;
6416 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006417
6418 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006419 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006420 reportParseError("invalid register");
6421 return false;
6422 }
6423 Parser.Lex(); // Eat "reg".
6424
6425 // If this is not the end of the statement, report an error.
6426 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6427 reportParseError("unexpected token, expected end of statement");
6428 return false;
6429 }
6430
6431 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6432
6433 Parser.Lex(); // Consume the EndOfStatement.
6434 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006435}
6436
6437bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006438 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006439 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006440 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006441 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006442 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006443 return false;
6444 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006445 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006446 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006447 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006448 return false;
6449}
6450
6451bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006452 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006453 Parser.Lex();
6454 // If this is not the end of the statement, report an error.
6455 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006456 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006457 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006458 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006459 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006460 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006461 Parser.Lex(); // Consume the EndOfStatement.
6462 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006463}
6464
6465bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006466 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006467 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006468 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006469 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006470 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006471 return false;
6472 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006473 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006474 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006475 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006476 return false;
6477}
6478
6479bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006480 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006481 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006482 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006483 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006484 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006485 return false;
6486 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006487 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006488 reportParseError("`noreorder' must be set before `nomacro'");
6489 return false;
6490 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006491 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006492 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006493 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006494 return false;
6495}
Jack Carterd76b2372013-03-21 21:44:16 +00006496
Daniel Sanders44934432014-08-07 12:03:36 +00006497bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006498 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006499 Parser.Lex();
6500
6501 // If this is not the end of the statement, report an error.
6502 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006503 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006504
6505 setFeatureBits(Mips::FeatureMSA, "msa");
6506 getTargetStreamer().emitDirectiveSetMsa();
6507 return false;
6508}
6509
6510bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006511 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006512 Parser.Lex();
6513
6514 // If this is not the end of the statement, report an error.
6515 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006516 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006517
6518 clearFeatureBits(Mips::FeatureMSA, "msa");
6519 getTargetStreamer().emitDirectiveSetNoMsa();
6520 return false;
6521}
6522
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006523bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006524 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006525 Parser.Lex(); // Eat "nodsp".
6526
6527 // If this is not the end of the statement, report an error.
6528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6529 reportParseError("unexpected token, expected end of statement");
6530 return false;
6531 }
6532
6533 clearFeatureBits(Mips::FeatureDSP, "dsp");
6534 getTargetStreamer().emitDirectiveSetNoDsp();
6535 return false;
6536}
6537
Toma Tabacucc2502d2014-11-04 17:18:07 +00006538bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006539 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006540 Parser.Lex(); // Eat "mips16".
6541
Jack Carter39536722014-01-22 23:08:42 +00006542 // If this is not the end of the statement, report an error.
6543 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006544 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006545 return false;
6546 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006547
6548 setFeatureBits(Mips::FeatureMips16, "mips16");
6549 getTargetStreamer().emitDirectiveSetMips16();
6550 Parser.Lex(); // Consume the EndOfStatement.
6551 return false;
6552}
6553
6554bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006555 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006556 Parser.Lex(); // Eat "nomips16".
6557
6558 // If this is not the end of the statement, report an error.
6559 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6560 reportParseError("unexpected token, expected end of statement");
6561 return false;
6562 }
6563
6564 clearFeatureBits(Mips::FeatureMips16, "mips16");
6565 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006566 Parser.Lex(); // Consume the EndOfStatement.
6567 return false;
6568}
6569
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006570bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006571 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006572 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006573 // Line can be: .set fp=32
6574 // .set fp=xx
6575 // .set fp=64
6576 Parser.Lex(); // Eat fp token
6577 AsmToken Tok = Parser.getTok();
6578 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006579 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006580 return false;
6581 }
6582 Parser.Lex(); // Eat '=' token.
6583 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006584
6585 if (!parseFpABIValue(FpAbiVal, ".set"))
6586 return false;
6587
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006588 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006589 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006590 return false;
6591 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006592 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006593 Parser.Lex(); // Consume the EndOfStatement.
6594 return false;
6595}
6596
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006597bool MipsAsmParser::parseSetOddSPRegDirective() {
6598 MCAsmParser &Parser = getParser();
6599
6600 Parser.Lex(); // Eat "oddspreg".
6601 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6602 reportParseError("unexpected token, expected end of statement");
6603 return false;
6604 }
6605
6606 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6607 getTargetStreamer().emitDirectiveSetOddSPReg();
6608 return false;
6609}
6610
6611bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6612 MCAsmParser &Parser = getParser();
6613
6614 Parser.Lex(); // Eat "nooddspreg".
6615 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6616 reportParseError("unexpected token, expected end of statement");
6617 return false;
6618 }
6619
6620 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6621 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6622 return false;
6623}
6624
Simon Dardis805f1e02017-07-11 21:28:36 +00006625bool MipsAsmParser::parseSetMtDirective() {
6626 MCAsmParser &Parser = getParser();
6627 Parser.Lex(); // Eat "mt".
6628
6629 // If this is not the end of the statement, report an error.
6630 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6631 reportParseError("unexpected token, expected end of statement");
6632 return false;
6633 }
6634
6635 setFeatureBits(Mips::FeatureMT, "mt");
6636 getTargetStreamer().emitDirectiveSetMt();
6637 Parser.Lex(); // Consume the EndOfStatement.
6638 return false;
6639}
6640
6641bool MipsAsmParser::parseSetNoMtDirective() {
6642 MCAsmParser &Parser = getParser();
6643 Parser.Lex(); // Eat "nomt".
6644
6645 // If this is not the end of the statement, report an error.
6646 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6647 reportParseError("unexpected token, expected end of statement");
6648 return false;
6649 }
6650
6651 clearFeatureBits(Mips::FeatureMT, "mt");
6652
6653 getTargetStreamer().emitDirectiveSetNoMt();
6654 Parser.Lex(); // Consume the EndOfStatement.
6655 return false;
6656}
6657
Toma Tabacu9db22db2014-09-09 10:15:38 +00006658bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006659 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006660 SMLoc Loc = getLexer().getLoc();
6661
6662 Parser.Lex();
6663 if (getLexer().isNot(AsmToken::EndOfStatement))
6664 return reportParseError("unexpected token, expected end of statement");
6665
6666 // Always keep an element on the options "stack" to prevent the user
6667 // from changing the initial options. This is how we remember them.
6668 if (AssemblerOptions.size() == 2)
6669 return reportParseError(Loc, ".set pop with no .set push");
6670
Akira Hatanakab11ef082015-11-14 06:35:56 +00006671 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006672 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006673 setAvailableFeatures(
6674 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6675 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006676
6677 getTargetStreamer().emitDirectiveSetPop();
6678 return false;
6679}
6680
6681bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006682 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006683 Parser.Lex();
6684 if (getLexer().isNot(AsmToken::EndOfStatement))
6685 return reportParseError("unexpected token, expected end of statement");
6686
6687 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006688 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006689 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006690
6691 getTargetStreamer().emitDirectiveSetPush();
6692 return false;
6693}
6694
Toma Tabacu29696502015-06-02 09:48:04 +00006695bool MipsAsmParser::parseSetSoftFloatDirective() {
6696 MCAsmParser &Parser = getParser();
6697 Parser.Lex();
6698 if (getLexer().isNot(AsmToken::EndOfStatement))
6699 return reportParseError("unexpected token, expected end of statement");
6700
6701 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6702 getTargetStreamer().emitDirectiveSetSoftFloat();
6703 return false;
6704}
6705
6706bool MipsAsmParser::parseSetHardFloatDirective() {
6707 MCAsmParser &Parser = getParser();
6708 Parser.Lex();
6709 if (getLexer().isNot(AsmToken::EndOfStatement))
6710 return reportParseError("unexpected token, expected end of statement");
6711
6712 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6713 getTargetStreamer().emitDirectiveSetHardFloat();
6714 return false;
6715}
6716
Jack Carterd76b2372013-03-21 21:44:16 +00006717bool MipsAsmParser::parseSetAssignment() {
6718 StringRef Name;
6719 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006720 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006721
6722 if (Parser.parseIdentifier(Name))
6723 reportParseError("expected identifier after .set");
6724
6725 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006726 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006727 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006728
Jack Carter3b2c96e2014-01-22 23:31:38 +00006729 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006730 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006731
Jim Grosbach6f482002015-05-18 18:43:14 +00006732 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006733 Sym->setVariableValue(Value);
6734
6735 return false;
6736}
Jack Carterd0bd6422013-04-18 00:41:53 +00006737
Toma Tabacu26647792014-09-09 12:52:14 +00006738bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006739 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006740 Parser.Lex();
6741 if (getLexer().isNot(AsmToken::EndOfStatement))
6742 return reportParseError("unexpected token, expected end of statement");
6743
6744 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006745 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006746 setAvailableFeatures(
6747 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6748 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006749 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6750
6751 getTargetStreamer().emitDirectiveSetMips0();
6752 return false;
6753}
6754
Toma Tabacu85618b32014-08-19 14:22:52 +00006755bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006756 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006757 Parser.Lex();
6758 if (getLexer().isNot(AsmToken::Equal))
6759 return reportParseError("unexpected token, expected equals sign");
6760
6761 Parser.Lex();
6762 StringRef Arch;
6763 if (Parser.parseIdentifier(Arch))
6764 return reportParseError("expected arch identifier");
6765
6766 StringRef ArchFeatureName =
6767 StringSwitch<StringRef>(Arch)
6768 .Case("mips1", "mips1")
6769 .Case("mips2", "mips2")
6770 .Case("mips3", "mips3")
6771 .Case("mips4", "mips4")
6772 .Case("mips5", "mips5")
6773 .Case("mips32", "mips32")
6774 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006775 .Case("mips32r3", "mips32r3")
6776 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006777 .Case("mips32r6", "mips32r6")
6778 .Case("mips64", "mips64")
6779 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006780 .Case("mips64r3", "mips64r3")
6781 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006782 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006783 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006784 .Case("r4000", "mips3") // This is an implementation of Mips3.
6785 .Default("");
6786
6787 if (ArchFeatureName.empty())
6788 return reportParseError("unsupported architecture");
6789
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006790 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6791 return reportParseError("mips64r6 does not support microMIPS");
6792
Toma Tabacu85618b32014-08-19 14:22:52 +00006793 selectArch(ArchFeatureName);
6794 getTargetStreamer().emitDirectiveSetArch(Arch);
6795 return false;
6796}
6797
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006798bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006799 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006800 Parser.Lex();
6801 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006802 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006803
Matheus Almeida2852af82014-04-22 10:15:54 +00006804 switch (Feature) {
6805 default:
6806 llvm_unreachable("Unimplemented feature");
6807 case Mips::FeatureDSP:
6808 setFeatureBits(Mips::FeatureDSP, "dsp");
6809 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006810 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006811 case Mips::FeatureDSPR2:
6812 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6813 getTargetStreamer().emitDirectiveSetDspr2();
6814 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006815 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006816 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006817 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006818 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006819 case Mips::FeatureMips1:
6820 selectArch("mips1");
6821 getTargetStreamer().emitDirectiveSetMips1();
6822 break;
6823 case Mips::FeatureMips2:
6824 selectArch("mips2");
6825 getTargetStreamer().emitDirectiveSetMips2();
6826 break;
6827 case Mips::FeatureMips3:
6828 selectArch("mips3");
6829 getTargetStreamer().emitDirectiveSetMips3();
6830 break;
6831 case Mips::FeatureMips4:
6832 selectArch("mips4");
6833 getTargetStreamer().emitDirectiveSetMips4();
6834 break;
6835 case Mips::FeatureMips5:
6836 selectArch("mips5");
6837 getTargetStreamer().emitDirectiveSetMips5();
6838 break;
6839 case Mips::FeatureMips32:
6840 selectArch("mips32");
6841 getTargetStreamer().emitDirectiveSetMips32();
6842 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006843 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006844 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006845 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006846 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006847 case Mips::FeatureMips32r3:
6848 selectArch("mips32r3");
6849 getTargetStreamer().emitDirectiveSetMips32R3();
6850 break;
6851 case Mips::FeatureMips32r5:
6852 selectArch("mips32r5");
6853 getTargetStreamer().emitDirectiveSetMips32R5();
6854 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006855 case Mips::FeatureMips32r6:
6856 selectArch("mips32r6");
6857 getTargetStreamer().emitDirectiveSetMips32R6();
6858 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006859 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006860 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006861 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006862 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006863 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006864 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006865 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006866 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006867 case Mips::FeatureMips64r3:
6868 selectArch("mips64r3");
6869 getTargetStreamer().emitDirectiveSetMips64R3();
6870 break;
6871 case Mips::FeatureMips64r5:
6872 selectArch("mips64r5");
6873 getTargetStreamer().emitDirectiveSetMips64R5();
6874 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006875 case Mips::FeatureMips64r6:
6876 selectArch("mips64r6");
6877 getTargetStreamer().emitDirectiveSetMips64R6();
6878 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006879 }
6880 return false;
6881}
6882
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006883bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006884 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006885 if (getLexer().isNot(AsmToken::Comma)) {
6886 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006887 return Error(Loc, ErrorStr);
6888 }
6889
Matheus Almeida2852af82014-04-22 10:15:54 +00006890 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006891 return true;
6892}
6893
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006894// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6895// In this class, it is only used for .cprestore.
6896// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6897// MipsTargetELFStreamer and MipsAsmParser.
6898bool MipsAsmParser::isPicAndNotNxxAbi() {
6899 return inPicMode() && !(isABI_N32() || isABI_N64());
6900}
6901
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006902bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006903 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006904 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006905
Toma Tabacudde4c462014-11-06 10:02:45 +00006906 if (inMips16Mode()) {
6907 reportParseError(".cpload is not supported in Mips16 mode");
6908 return false;
6909 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006910
David Blaikie960ea3f2014-06-08 16:18:35 +00006911 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006912 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006913 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6914 reportParseError("expected register containing function address");
6915 return false;
6916 }
6917
David Blaikie960ea3f2014-06-08 16:18:35 +00006918 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6919 if (!RegOpnd.isGPRAsmReg()) {
6920 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006921 return false;
6922 }
6923
Toma Tabacudde4c462014-11-06 10:02:45 +00006924 // If this is not the end of the statement, report an error.
6925 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6926 reportParseError("unexpected token, expected end of statement");
6927 return false;
6928 }
6929
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006930 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006931 return false;
6932}
6933
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006934bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6935 MCAsmParser &Parser = getParser();
6936
6937 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6938 // is used in non-PIC mode.
6939
6940 if (inMips16Mode()) {
6941 reportParseError(".cprestore is not supported in Mips16 mode");
6942 return false;
6943 }
6944
6945 // Get the stack offset value.
6946 const MCExpr *StackOffset;
6947 int64_t StackOffsetVal;
6948 if (Parser.parseExpression(StackOffset)) {
6949 reportParseError("expected stack offset value");
6950 return false;
6951 }
6952
6953 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6954 reportParseError("stack offset is not an absolute expression");
6955 return false;
6956 }
6957
6958 if (StackOffsetVal < 0) {
6959 Warning(Loc, ".cprestore with negative stack offset has no effect");
6960 IsCpRestoreSet = false;
6961 } else {
6962 IsCpRestoreSet = true;
6963 CpRestoreOffset = StackOffsetVal;
6964 }
6965
6966 // If this is not the end of the statement, report an error.
6967 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6968 reportParseError("unexpected token, expected end of statement");
6969 return false;
6970 }
6971
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006972 if (!getTargetStreamer().emitDirectiveCpRestore(
6973 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006974 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006975 Parser.Lex(); // Consume the EndOfStatement.
6976 return false;
6977}
6978
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006979bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006980 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006981 unsigned FuncReg;
6982 unsigned Save;
6983 bool SaveIsReg = true;
6984
Matheus Almeida7e815762014-06-18 13:08:59 +00006985 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006986 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006987 if (ResTy == MatchOperand_NoMatch) {
6988 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006989 return false;
6990 }
6991
6992 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6993 if (!FuncRegOpnd.isGPRAsmReg()) {
6994 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006995 return false;
6996 }
6997
6998 FuncReg = FuncRegOpnd.getGPR32Reg();
6999 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007000
Toma Tabacu65f10572014-09-16 15:00:52 +00007001 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007002 return true;
7003
Toma Tabacu13964452014-09-04 13:23:44 +00007004 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007005 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007006 const MCExpr *OffsetExpr;
7007 int64_t OffsetVal;
7008 SMLoc ExprLoc = getLexer().getLoc();
7009
7010 if (Parser.parseExpression(OffsetExpr) ||
7011 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7012 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007013 return false;
7014 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007015
7016 Save = OffsetVal;
7017 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007018 } else {
7019 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7020 if (!SaveOpnd.isGPRAsmReg()) {
7021 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007022 return false;
7023 }
7024 Save = SaveOpnd.getGPR32Reg();
7025 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007026
Toma Tabacu65f10572014-09-16 15:00:52 +00007027 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007028 return true;
7029
Toma Tabacu8874eac2015-02-18 13:46:53 +00007030 const MCExpr *Expr;
7031 if (Parser.parseExpression(Expr)) {
7032 reportParseError("expected expression");
7033 return false;
7034 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007035
Toma Tabacu8874eac2015-02-18 13:46:53 +00007036 if (Expr->getKind() != MCExpr::SymbolRef) {
7037 reportParseError("expected symbol");
7038 return false;
7039 }
7040 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7041
Daniel Sandersf173dda2015-09-22 10:50:09 +00007042 CpSaveLocation = Save;
7043 CpSaveLocationIsRegister = SaveIsReg;
7044
Toma Tabacu8874eac2015-02-18 13:46:53 +00007045 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7046 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007047 return false;
7048}
7049
Daniel Sandersf173dda2015-09-22 10:50:09 +00007050bool MipsAsmParser::parseDirectiveCPReturn() {
7051 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7052 CpSaveLocationIsRegister);
7053 return false;
7054}
7055
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007056bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007057 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007058 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7059 const AsmToken &Tok = Parser.getTok();
7060
7061 if (Tok.getString() == "2008") {
7062 Parser.Lex();
7063 getTargetStreamer().emitDirectiveNaN2008();
7064 return false;
7065 } else if (Tok.getString() == "legacy") {
7066 Parser.Lex();
7067 getTargetStreamer().emitDirectiveNaNLegacy();
7068 return false;
7069 }
7070 }
7071 // If we don't recognize the option passed to the .nan
7072 // directive (e.g. no option or unknown option), emit an error.
7073 reportParseError("invalid option in .nan directive");
7074 return false;
7075}
7076
Jack Carter0b744b32012-10-04 02:29:46 +00007077bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007078 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00007079 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00007080 const AsmToken &Tok = Parser.getTok();
7081
7082 if (Tok.getString() == "noat") {
7083 return parseSetNoAtDirective();
7084 } else if (Tok.getString() == "at") {
7085 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00007086 } else if (Tok.getString() == "arch") {
7087 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00007088 } else if (Tok.getString() == "bopt") {
7089 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
7090 getParser().Lex();
7091 return false;
7092 } else if (Tok.getString() == "nobopt") {
7093 // We're already running in nobopt mode, so nothing to do.
7094 getParser().Lex();
7095 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007096 } else if (Tok.getString() == "fp") {
7097 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007098 } else if (Tok.getString() == "oddspreg") {
7099 return parseSetOddSPRegDirective();
7100 } else if (Tok.getString() == "nooddspreg") {
7101 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00007102 } else if (Tok.getString() == "pop") {
7103 return parseSetPopDirective();
7104 } else if (Tok.getString() == "push") {
7105 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00007106 } else if (Tok.getString() == "reorder") {
7107 return parseSetReorderDirective();
7108 } else if (Tok.getString() == "noreorder") {
7109 return parseSetNoReorderDirective();
7110 } else if (Tok.getString() == "macro") {
7111 return parseSetMacroDirective();
7112 } else if (Tok.getString() == "nomacro") {
7113 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00007114 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00007115 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007116 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00007117 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007118 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007119 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007120 getTargetStreamer().emitDirectiveSetNoMicroMips();
7121 Parser.eatToEndOfStatement();
7122 return false;
7123 } else if (Tok.getString() == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007124 if (hasMips64r6()) {
7125 Error(Tok.getLoc(), ".set micromips directive is not supported with MIPS64R6");
7126 return false;
7127 }
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") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007160 if (inMicroMipsMode()) {
7161 Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS");
7162 return false;
7163 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007164 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00007165 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007166 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00007167 } else if (Tok.getString() == "dspr2") {
7168 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00007169 } else if (Tok.getString() == "nodsp") {
7170 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00007171 } else if (Tok.getString() == "msa") {
7172 return parseSetMsaDirective();
7173 } else if (Tok.getString() == "nomsa") {
7174 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00007175 } else if (Tok.getString() == "mt") {
7176 return parseSetMtDirective();
7177 } else if (Tok.getString() == "nomt") {
7178 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00007179 } else if (Tok.getString() == "softfloat") {
7180 return parseSetSoftFloatDirective();
7181 } else if (Tok.getString() == "hardfloat") {
7182 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00007183 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00007184 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00007185 parseSetAssignment();
7186 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00007187 }
Jack Carter07c818d2013-01-25 01:31:34 +00007188
Jack Carter0b744b32012-10-04 02:29:46 +00007189 return true;
7190}
7191
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007192/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007193/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007194bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007195 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007196 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007197 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007198 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007199 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007200 return true;
7201
7202 getParser().getStreamer().EmitValue(Value, Size);
7203
7204 if (getLexer().is(AsmToken::EndOfStatement))
7205 break;
7206
Jack Carter07c818d2013-01-25 01:31:34 +00007207 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007208 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007209 Parser.Lex();
7210 }
7211 }
7212
7213 Parser.Lex();
7214 return false;
7215}
7216
Vladimir Medic4c299852013-11-06 11:27:05 +00007217/// parseDirectiveGpWord
7218/// ::= .gpword local_sym
7219bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007220 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007221 const MCExpr *Value;
7222 // EmitGPRel32Value requires an expression, so we are using base class
7223 // method to evaluate the expression.
7224 if (getParser().parseExpression(Value))
7225 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007226 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007227
Vladimir Medice10c1122013-11-13 13:18:04 +00007228 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007229 return Error(getLexer().getLoc(),
7230 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007231 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007232 return false;
7233}
7234
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007235/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007236/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007237bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007238 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007239 const MCExpr *Value;
7240 // EmitGPRel64Value requires an expression, so we are using base class
7241 // method to evaluate the expression.
7242 if (getParser().parseExpression(Value))
7243 return true;
7244 getParser().getStreamer().EmitGPRel64Value(Value);
7245
7246 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007247 return Error(getLexer().getLoc(),
7248 "unexpected token, expected end of statement");
7249 Parser.Lex(); // Eat EndOfStatement token.
7250 return false;
7251}
7252
7253/// parseDirectiveDtpRelWord
7254/// ::= .dtprelword tls_sym
7255bool MipsAsmParser::parseDirectiveDtpRelWord() {
7256 MCAsmParser &Parser = getParser();
7257 const MCExpr *Value;
7258 // EmitDTPRel32Value requires an expression, so we are using base class
7259 // method to evaluate the expression.
7260 if (getParser().parseExpression(Value))
7261 return true;
7262 getParser().getStreamer().EmitDTPRel32Value(Value);
7263
7264 if (getLexer().isNot(AsmToken::EndOfStatement))
7265 return Error(getLexer().getLoc(),
7266 "unexpected token, expected end of statement");
7267 Parser.Lex(); // Eat EndOfStatement token.
7268 return false;
7269}
7270
7271/// parseDirectiveDtpRelDWord
7272/// ::= .dtpreldword tls_sym
7273bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7274 MCAsmParser &Parser = getParser();
7275 const MCExpr *Value;
7276 // EmitDTPRel64Value requires an expression, so we are using base class
7277 // method to evaluate the expression.
7278 if (getParser().parseExpression(Value))
7279 return true;
7280 getParser().getStreamer().EmitDTPRel64Value(Value);
7281
7282 if (getLexer().isNot(AsmToken::EndOfStatement))
7283 return Error(getLexer().getLoc(),
7284 "unexpected token, expected end of statement");
7285 Parser.Lex(); // Eat EndOfStatement token.
7286 return false;
7287}
7288
7289/// parseDirectiveTpRelWord
7290/// ::= .tprelword tls_sym
7291bool MipsAsmParser::parseDirectiveTpRelWord() {
7292 MCAsmParser &Parser = getParser();
7293 const MCExpr *Value;
7294 // EmitTPRel32Value requires an expression, so we are using base class
7295 // method to evaluate the expression.
7296 if (getParser().parseExpression(Value))
7297 return true;
7298 getParser().getStreamer().EmitTPRel32Value(Value);
7299
7300 if (getLexer().isNot(AsmToken::EndOfStatement))
7301 return Error(getLexer().getLoc(),
7302 "unexpected token, expected end of statement");
7303 Parser.Lex(); // Eat EndOfStatement token.
7304 return false;
7305}
7306
7307/// parseDirectiveTpRelDWord
7308/// ::= .tpreldword tls_sym
7309bool MipsAsmParser::parseDirectiveTpRelDWord() {
7310 MCAsmParser &Parser = getParser();
7311 const MCExpr *Value;
7312 // EmitTPRel64Value requires an expression, so we are using base class
7313 // method to evaluate the expression.
7314 if (getParser().parseExpression(Value))
7315 return true;
7316 getParser().getStreamer().EmitTPRel64Value(Value);
7317
7318 if (getLexer().isNot(AsmToken::EndOfStatement))
7319 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007320 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007321 Parser.Lex(); // Eat EndOfStatement token.
7322 return false;
7323}
7324
Jack Carter0cd3c192014-01-06 23:27:31 +00007325bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007326 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007327 // Get the option token.
7328 AsmToken Tok = Parser.getTok();
7329 // At the moment only identifiers are supported.
7330 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007331 return Error(Parser.getTok().getLoc(),
7332 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007333 }
7334
7335 StringRef Option = Tok.getIdentifier();
7336
7337 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007338 // MipsAsmParser needs to know if the current PIC mode changes.
7339 IsPicEnabled = false;
7340
Jack Carter0cd3c192014-01-06 23:27:31 +00007341 getTargetStreamer().emitDirectiveOptionPic0();
7342 Parser.Lex();
7343 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007344 return Error(Parser.getTok().getLoc(),
7345 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007346 }
7347 return false;
7348 }
7349
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007350 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007351 // MipsAsmParser needs to know if the current PIC mode changes.
7352 IsPicEnabled = true;
7353
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007354 getTargetStreamer().emitDirectiveOptionPic2();
7355 Parser.Lex();
7356 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007357 return Error(Parser.getTok().getLoc(),
7358 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007359 }
7360 return false;
7361 }
7362
Jack Carter0cd3c192014-01-06 23:27:31 +00007363 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007364 Warning(Parser.getTok().getLoc(),
7365 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007366 Parser.eatToEndOfStatement();
7367 return false;
7368}
7369
Toma Tabacu9ca50962015-04-16 09:53:47 +00007370/// parseInsnDirective
7371/// ::= .insn
7372bool MipsAsmParser::parseInsnDirective() {
7373 // If this is not the end of the statement, report an error.
7374 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7375 reportParseError("unexpected token, expected end of statement");
7376 return false;
7377 }
7378
7379 // The actual label marking happens in
7380 // MipsELFStreamer::createPendingLabelRelocs().
7381 getTargetStreamer().emitDirectiveInsn();
7382
7383 getParser().Lex(); // Eat EndOfStatement token.
7384 return false;
7385}
7386
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007387/// parseRSectionDirective
7388/// ::= .rdata
7389bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7390 // If this is not the end of the statement, report an error.
7391 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7392 reportParseError("unexpected token, expected end of statement");
7393 return false;
7394 }
7395
7396 MCSection *ELFSection = getContext().getELFSection(
7397 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7398 getParser().getStreamer().SwitchSection(ELFSection);
7399
7400 getParser().Lex(); // Eat EndOfStatement token.
7401 return false;
7402}
7403
Simon Atanasyanbe186202016-02-11 06:45:54 +00007404/// parseSSectionDirective
7405/// ::= .sbss
7406/// ::= .sdata
7407bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7408 // If this is not the end of the statement, report an error.
7409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7410 reportParseError("unexpected token, expected end of statement");
7411 return false;
7412 }
7413
7414 MCSection *ELFSection = getContext().getELFSection(
7415 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7416 getParser().getStreamer().SwitchSection(ELFSection);
7417
7418 getParser().Lex(); // Eat EndOfStatement token.
7419 return false;
7420}
7421
Daniel Sanders7e527422014-07-10 13:38:23 +00007422/// parseDirectiveModule
7423/// ::= .module oddspreg
7424/// ::= .module nooddspreg
7425/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007426/// ::= .module softfloat
7427/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007428/// ::= .module mt
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007429bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007430 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007431 MCAsmLexer &Lexer = getLexer();
7432 SMLoc L = Lexer.getLoc();
7433
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007434 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007435 // TODO : get a better message.
7436 reportParseError(".module directive must appear before any code");
7437 return false;
7438 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007439
Toma Tabacuc405c822015-01-23 10:40:19 +00007440 StringRef Option;
7441 if (Parser.parseIdentifier(Option)) {
7442 reportParseError("expected .module option identifier");
7443 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007444 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007445
Toma Tabacuc405c822015-01-23 10:40:19 +00007446 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007447 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007448
Toma Tabacu3c499582015-06-25 10:56:57 +00007449 // Synchronize the abiflags information with the FeatureBits information we
7450 // changed above.
7451 getTargetStreamer().updateABIInfo(*this);
7452
7453 // If printing assembly, use the recently updated abiflags information.
7454 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7455 // emitted at the end).
7456 getTargetStreamer().emitDirectiveModuleOddSPReg();
7457
Toma Tabacuc405c822015-01-23 10:40:19 +00007458 // If this is not the end of the statement, report an error.
7459 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7460 reportParseError("unexpected token, expected end of statement");
7461 return false;
7462 }
7463
7464 return false; // parseDirectiveModule has finished successfully.
7465 } else if (Option == "nooddspreg") {
7466 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007467 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007468 }
7469
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007470 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007471
Toma Tabacu3c499582015-06-25 10:56:57 +00007472 // Synchronize the abiflags information with the FeatureBits information we
7473 // changed above.
7474 getTargetStreamer().updateABIInfo(*this);
7475
7476 // If printing assembly, use the recently updated abiflags information.
7477 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7478 // emitted at the end).
7479 getTargetStreamer().emitDirectiveModuleOddSPReg();
7480
Toma Tabacuc405c822015-01-23 10:40:19 +00007481 // If this is not the end of the statement, report an error.
7482 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7483 reportParseError("unexpected token, expected end of statement");
7484 return false;
7485 }
7486
7487 return false; // parseDirectiveModule has finished successfully.
7488 } else if (Option == "fp") {
7489 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007490 } else if (Option == "softfloat") {
7491 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7492
7493 // Synchronize the ABI Flags information with the FeatureBits information we
7494 // updated above.
7495 getTargetStreamer().updateABIInfo(*this);
7496
7497 // If printing assembly, use the recently updated ABI Flags information.
7498 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7499 // emitted later).
7500 getTargetStreamer().emitDirectiveModuleSoftFloat();
7501
7502 // If this is not the end of the statement, report an error.
7503 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7504 reportParseError("unexpected token, expected end of statement");
7505 return false;
7506 }
7507
7508 return false; // parseDirectiveModule has finished successfully.
7509 } else if (Option == "hardfloat") {
7510 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7511
7512 // Synchronize the ABI Flags information with the FeatureBits information we
7513 // updated above.
7514 getTargetStreamer().updateABIInfo(*this);
7515
7516 // If printing assembly, use the recently updated ABI Flags information.
7517 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7518 // emitted later).
7519 getTargetStreamer().emitDirectiveModuleHardFloat();
7520
7521 // If this is not the end of the statement, report an error.
7522 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7523 reportParseError("unexpected token, expected end of statement");
7524 return false;
7525 }
7526
7527 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007528 } else if (Option == "mt") {
7529 setModuleFeatureBits(Mips::FeatureMT, "mt");
7530
7531 // Synchronize the ABI Flags information with the FeatureBits information we
7532 // updated above.
7533 getTargetStreamer().updateABIInfo(*this);
7534
Simon Dardisd9611922017-07-11 21:36:58 +00007535 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007536 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7537 // emitted later).
7538 getTargetStreamer().emitDirectiveModuleMT();
7539
7540 // If this is not the end of the statement, report an error.
7541 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7542 reportParseError("unexpected token, expected end of statement");
7543 return false;
7544 }
7545
7546 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007547 } else {
7548 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7549 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007550}
7551
7552/// parseDirectiveModuleFP
7553/// ::= =32
7554/// ::= =xx
7555/// ::= =64
7556bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007557 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007558 MCAsmLexer &Lexer = getLexer();
7559
7560 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007561 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007562 return false;
7563 }
7564 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007565
Daniel Sanders7e527422014-07-10 13:38:23 +00007566 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007567 if (!parseFpABIValue(FpABI, ".module"))
7568 return false;
7569
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007570 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007571 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007572 return false;
7573 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007574
Toma Tabacua64e5402015-06-25 12:44:38 +00007575 // Synchronize the abiflags information with the FeatureBits information we
7576 // changed above.
7577 getTargetStreamer().updateABIInfo(*this);
7578
7579 // If printing assembly, use the recently updated abiflags information.
7580 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7581 // emitted at the end).
7582 getTargetStreamer().emitDirectiveModuleFP();
7583
Daniel Sanders7e527422014-07-10 13:38:23 +00007584 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007585 return false;
7586}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007587
Daniel Sanders7e527422014-07-10 13:38:23 +00007588bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007589 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007590 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007591 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007592 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007593
7594 if (Lexer.is(AsmToken::Identifier)) {
7595 StringRef Value = Parser.getTok().getString();
7596 Parser.Lex();
7597
7598 if (Value != "xx") {
7599 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7600 return false;
7601 }
7602
7603 if (!isABI_O32()) {
7604 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7605 return false;
7606 }
7607
Daniel Sanders7e527422014-07-10 13:38:23 +00007608 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007609 if (ModuleLevelOptions) {
7610 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7611 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7612 } else {
7613 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7614 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7615 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007616 return true;
7617 }
7618
7619 if (Lexer.is(AsmToken::Integer)) {
7620 unsigned Value = Parser.getTok().getIntVal();
7621 Parser.Lex();
7622
7623 if (Value != 32 && Value != 64) {
7624 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7625 return false;
7626 }
7627
7628 if (Value == 32) {
7629 if (!isABI_O32()) {
7630 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7631 return false;
7632 }
7633
Daniel Sanders7e527422014-07-10 13:38:23 +00007634 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007635 if (ModuleLevelOptions) {
7636 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7637 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7638 } else {
7639 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7640 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7641 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007642 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007643 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007644 if (ModuleLevelOptions) {
7645 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7646 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7647 } else {
7648 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7649 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7650 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007651 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007652
Daniel Sanders7e527422014-07-10 13:38:23 +00007653 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007654 }
7655
7656 return false;
7657}
7658
Jack Carter0b744b32012-10-04 02:29:46 +00007659bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007660 // This returns false if this function recognizes the directive
7661 // regardless of whether it is successfully handles or reports an
7662 // error. Otherwise it returns true to give the generic parser a
7663 // chance at recognizing it.
7664
Rafael Espindola961d4692014-11-11 05:18:41 +00007665 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007666 StringRef IDVal = DirectiveID.getString();
7667
Nirav Dave996fc132016-05-05 14:15:46 +00007668 if (IDVal == ".cpload") {
7669 parseDirectiveCpLoad(DirectiveID.getLoc());
7670 return false;
7671 }
7672 if (IDVal == ".cprestore") {
7673 parseDirectiveCpRestore(DirectiveID.getLoc());
7674 return false;
7675 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007676 if (IDVal == ".dword") {
7677 parseDataDirective(8, DirectiveID.getLoc());
7678 return false;
7679 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007680 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007681 StringRef SymbolName;
7682
7683 if (Parser.parseIdentifier(SymbolName)) {
7684 reportParseError("expected identifier after .ent");
7685 return false;
7686 }
7687
7688 // There's an undocumented extension that allows an integer to
7689 // follow the name of the procedure which AFAICS is ignored by GAS.
7690 // Example: .ent foo,2
7691 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7692 if (getLexer().isNot(AsmToken::Comma)) {
7693 // Even though we accept this undocumented extension for compatibility
7694 // reasons, the additional integer argument does not actually change
7695 // the behaviour of the '.ent' directive, so we would like to discourage
7696 // its use. We do this by not referring to the extended version in
7697 // error messages which are not directly related to its use.
7698 reportParseError("unexpected token, expected end of statement");
7699 return false;
7700 }
7701 Parser.Lex(); // Eat the comma.
7702 const MCExpr *DummyNumber;
7703 int64_t DummyNumberVal;
7704 // If the user was explicitly trying to use the extended version,
7705 // we still give helpful extension-related error messages.
7706 if (Parser.parseExpression(DummyNumber)) {
7707 reportParseError("expected number after comma");
7708 return false;
7709 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007710 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007711 reportParseError("expected an absolute expression after comma");
7712 return false;
7713 }
7714 }
7715
7716 // If this is not the end of the statement, report an error.
7717 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7718 reportParseError("unexpected token, expected end of statement");
7719 return false;
7720 }
7721
Jim Grosbach6f482002015-05-18 18:43:14 +00007722 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007723
7724 getTargetStreamer().emitDirectiveEnt(*Sym);
7725 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007726 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007727 return false;
7728 }
7729
Jack Carter07c818d2013-01-25 01:31:34 +00007730 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007731 StringRef SymbolName;
7732
7733 if (Parser.parseIdentifier(SymbolName)) {
7734 reportParseError("expected identifier after .end");
7735 return false;
7736 }
7737
7738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7739 reportParseError("unexpected token, expected end of statement");
7740 return false;
7741 }
7742
7743 if (CurrentFn == nullptr) {
7744 reportParseError(".end used without .ent");
7745 return false;
7746 }
7747
7748 if ((SymbolName != CurrentFn->getName())) {
7749 reportParseError(".end symbol does not match .ent symbol");
7750 return false;
7751 }
7752
7753 getTargetStreamer().emitDirectiveEnd(SymbolName);
7754 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007755 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007756 return false;
7757 }
7758
Jack Carter07c818d2013-01-25 01:31:34 +00007759 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007760 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7761 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007762 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007763 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7764 reportParseError("expected stack register");
7765 return false;
7766 }
7767
7768 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7769 if (!StackRegOpnd.isGPRAsmReg()) {
7770 reportParseError(StackRegOpnd.getStartLoc(),
7771 "expected general purpose register");
7772 return false;
7773 }
7774 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7775
7776 if (Parser.getTok().is(AsmToken::Comma))
7777 Parser.Lex();
7778 else {
7779 reportParseError("unexpected token, expected comma");
7780 return false;
7781 }
7782
7783 // Parse the frame size.
7784 const MCExpr *FrameSize;
7785 int64_t FrameSizeVal;
7786
7787 if (Parser.parseExpression(FrameSize)) {
7788 reportParseError("expected frame size value");
7789 return false;
7790 }
7791
Jim Grosbach13760bd2015-05-30 01:25:56 +00007792 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007793 reportParseError("frame size not an absolute expression");
7794 return false;
7795 }
7796
7797 if (Parser.getTok().is(AsmToken::Comma))
7798 Parser.Lex();
7799 else {
7800 reportParseError("unexpected token, expected comma");
7801 return false;
7802 }
7803
7804 // Parse the return register.
7805 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007806 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007807 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7808 reportParseError("expected return register");
7809 return false;
7810 }
7811
7812 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7813 if (!ReturnRegOpnd.isGPRAsmReg()) {
7814 reportParseError(ReturnRegOpnd.getStartLoc(),
7815 "expected general purpose register");
7816 return false;
7817 }
7818
7819 // If this is not the end of the statement, report an error.
7820 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7821 reportParseError("unexpected token, expected end of statement");
7822 return false;
7823 }
7824
7825 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7826 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007827 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007828 return false;
7829 }
7830
Jack Carter07c818d2013-01-25 01:31:34 +00007831 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007832 parseDirectiveSet();
7833 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007834 }
7835
Daniel Sandersd97a6342014-08-13 10:07:34 +00007836 if (IDVal == ".mask" || IDVal == ".fmask") {
7837 // .mask bitmask, frame_offset
7838 // bitmask: One bit for each register used.
7839 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7840 // first register is expected to be saved.
7841 // Examples:
7842 // .mask 0x80000000, -4
7843 // .fmask 0x80000000, -4
7844 //
Jack Carterbe332172012-09-07 00:48:02 +00007845
Daniel Sandersd97a6342014-08-13 10:07:34 +00007846 // Parse the bitmask
7847 const MCExpr *BitMask;
7848 int64_t BitMaskVal;
7849
7850 if (Parser.parseExpression(BitMask)) {
7851 reportParseError("expected bitmask value");
7852 return false;
7853 }
7854
Jim Grosbach13760bd2015-05-30 01:25:56 +00007855 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007856 reportParseError("bitmask not an absolute expression");
7857 return false;
7858 }
7859
7860 if (Parser.getTok().is(AsmToken::Comma))
7861 Parser.Lex();
7862 else {
7863 reportParseError("unexpected token, expected comma");
7864 return false;
7865 }
7866
7867 // Parse the frame_offset
7868 const MCExpr *FrameOffset;
7869 int64_t FrameOffsetVal;
7870
7871 if (Parser.parseExpression(FrameOffset)) {
7872 reportParseError("expected frame offset value");
7873 return false;
7874 }
7875
Jim Grosbach13760bd2015-05-30 01:25:56 +00007876 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007877 reportParseError("frame offset not an absolute expression");
7878 return false;
7879 }
7880
7881 // If this is not the end of the statement, report an error.
7882 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7883 reportParseError("unexpected token, expected end of statement");
7884 return false;
7885 }
7886
7887 if (IDVal == ".mask")
7888 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7889 else
7890 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007891 return false;
7892 }
7893
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007894 if (IDVal == ".nan")
7895 return parseDirectiveNaN();
7896
Jack Carter07c818d2013-01-25 01:31:34 +00007897 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007898 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007899 return false;
7900 }
7901
Rafael Espindolab59fb732014-03-28 18:50:26 +00007902 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007903 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007904 return false;
7905 }
7906
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007907 if (IDVal == ".dtprelword") {
7908 parseDirectiveDtpRelWord();
7909 return false;
7910 }
7911
7912 if (IDVal == ".dtpreldword") {
7913 parseDirectiveDtpRelDWord();
7914 return false;
7915 }
7916
7917 if (IDVal == ".tprelword") {
7918 parseDirectiveTpRelWord();
7919 return false;
7920 }
7921
7922 if (IDVal == ".tpreldword") {
7923 parseDirectiveTpRelDWord();
7924 return false;
7925 }
7926
Jack Carter07c818d2013-01-25 01:31:34 +00007927 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007928 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007929 return false;
7930 }
7931
Scott Egertond1aeb052016-02-15 16:11:51 +00007932 if (IDVal == ".hword") {
7933 parseDataDirective(2, DirectiveID.getLoc());
7934 return false;
7935 }
7936
Nirav Dave996fc132016-05-05 14:15:46 +00007937 if (IDVal == ".option") {
7938 parseDirectiveOption();
7939 return false;
7940 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007941
7942 if (IDVal == ".abicalls") {
7943 getTargetStreamer().emitDirectiveAbiCalls();
7944 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007945 Error(Parser.getTok().getLoc(),
7946 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007947 }
7948 return false;
7949 }
7950
Nirav Dave996fc132016-05-05 14:15:46 +00007951 if (IDVal == ".cpsetup") {
7952 parseDirectiveCPSetup();
7953 return false;
7954 }
7955 if (IDVal == ".cpreturn") {
7956 parseDirectiveCPReturn();
7957 return false;
7958 }
7959 if (IDVal == ".module") {
7960 parseDirectiveModule();
7961 return false;
7962 }
7963 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7964 parseInternalDirectiveReallowModule();
7965 return false;
7966 }
7967 if (IDVal == ".insn") {
7968 parseInsnDirective();
7969 return false;
7970 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007971 if (IDVal == ".rdata") {
7972 parseRSectionDirective(".rodata");
7973 return false;
7974 }
Nirav Dave996fc132016-05-05 14:15:46 +00007975 if (IDVal == ".sbss") {
7976 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7977 return false;
7978 }
7979 if (IDVal == ".sdata") {
7980 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7981 return false;
7982 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007983
Rafael Espindola870c4e92012-01-11 03:56:41 +00007984 return true;
7985}
7986
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007987bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7988 // If this is not the end of the statement, report an error.
7989 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7990 reportParseError("unexpected token, expected end of statement");
7991 return false;
7992 }
7993
7994 getTargetStreamer().reallowModuleDirective();
7995
7996 getParser().Lex(); // Eat EndOfStatement token.
7997 return false;
7998}
7999
Rafael Espindola870c4e92012-01-11 03:56:41 +00008000extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008001 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8002 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8003 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8004 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008005}
Jack Carterb4dbc172012-09-05 23:34:03 +00008006
8007#define GET_REGISTER_MATCHER
8008#define GET_MATCHER_IMPLEMENTATION
8009#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008010
8011bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8012 // Find the appropriate table for this asm variant.
8013 const MatchEntry *Start, *End;
8014 switch (VariantID) {
8015 default: llvm_unreachable("invalid variant!");
8016 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8017 }
8018 // Search the table.
8019 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8020 return MnemonicRange.first != MnemonicRange.second;
8021}