blob: 6eb01b270a4e89a0af85675af0310363bfe61d6b [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();
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000351 bool parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000352 bool parseSetNoVirtDirective();
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000353 bool parseSetNoGINVDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000354
Jack Carterd76b2372013-03-21 21:44:16 +0000355 bool parseSetAssignment();
356
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000357 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000358 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000359 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000360 bool parseDirectiveDtpRelWord();
361 bool parseDirectiveDtpRelDWord();
362 bool parseDirectiveTpRelWord();
363 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000364 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000365 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000366 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
367 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000368
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000369 bool parseInternalDirectiveReallowModule();
370
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000371 bool eatComma(StringRef ErrorStr);
372
Jack Carter1ac53222013-02-20 23:11:17 +0000373 int matchCPURegisterName(StringRef Symbol);
374
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000375 int matchHWRegsRegisterName(StringRef Symbol);
376
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000377 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000378
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000379 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000380
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000381 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000382
Jack Carter5dc8ac92013-09-25 23:50:44 +0000383 int matchMSA128RegisterName(StringRef Name);
384
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000385 int matchMSA128CtrlRegisterName(StringRef Name);
386
Jack Carterd0bd6422013-04-18 00:41:53 +0000387 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000388
Toma Tabacu89a712b2015-04-15 10:48:56 +0000389 /// Returns the internal register number for the current AT. Also checks if
390 /// the current AT is unavailable (set to $0) and gives an error if it is.
391 /// This should be used in pseudo-instruction expansions which need AT.
392 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000393
Simon Dardis3aa8a902017-02-06 12:43:46 +0000394 bool canUseATReg();
395
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000396 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
397 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000398
399 // Helper function that checks if the value of a vector index is within the
400 // boundaries of accepted values for each RegisterKind
401 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
402 bool validateMSAIndex(int Val, int RegKind);
403
Daniel Sandersf0df2212014-08-04 12:20:00 +0000404 // Selects a new architecture by updating the FeatureBits with the necessary
405 // info including implied dependencies.
406 // Internally, it clears all the feature bits related to *any* architecture
407 // and selects the new one using the ToggleFeature functionality of the
408 // MCSubtargetInfo object that handles implied dependencies. The reason we
409 // clear all the arch related bits manually is because ToggleFeature only
410 // clears the features that imply the feature being cleared and not the
411 // features implied by the feature being cleared. This is easier to see
412 // with an example:
413 // --------------------------------------------------
414 // | Feature | Implies |
415 // | -------------------------------------------------|
416 // | FeatureMips1 | None |
417 // | FeatureMips2 | FeatureMips1 |
418 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
419 // | FeatureMips4 | FeatureMips3 |
420 // | ... | |
421 // --------------------------------------------------
422 //
423 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
424 // FeatureMipsGP64 | FeatureMips1)
425 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
426 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000427 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000428 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000429 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
430 STI.setFeatureBits(FeatureBits);
431 setAvailableFeatures(
432 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000433 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000434 }
435
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000436 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000437 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000438 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000439 setAvailableFeatures(
440 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000441 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000442 }
443 }
444
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000445 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000446 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000447 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000448 setAvailableFeatures(
449 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000450 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000451 }
452 }
453
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000454 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
455 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000457 }
458
459 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
460 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000461 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000462 }
463
Rafael Espindola870c4e92012-01-11 03:56:41 +0000464public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000465 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000466 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000467 Match_RequiresDifferentOperands,
468 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000469 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000470 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000471 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000472 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000473 Match_RequiresPosSizeRange0_32,
474 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000475 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000476#define GET_OPERAND_DIAGNOSTIC_TYPES
477#include "MipsGenAsmMatcher.inc"
478#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000479 };
480
Akira Hatanakab11ef082015-11-14 06:35:56 +0000481 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000483 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000484 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
485 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000486 MCAsmParserExtension::Initialize(parser);
487
Toma Tabacu11e14a92015-04-21 11:50:52 +0000488 parser.addAliasForDirective(".asciiz", ".asciz");
489
Jack Carterb4dbc172012-09-05 23:34:03 +0000490 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000491 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000492
Toma Tabacu9db22db2014-09-09 10:15:38 +0000493 // Remember the initial assembler options. The user can not modify these.
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 Sandersa39ef1c2015-08-17 10:11:55 +0000496
Toma Tabacu9db22db2014-09-09 10:15:38 +0000497 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000498 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000500
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000501 getTargetStreamer().updateABIInfo(*this);
502
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000503 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000504 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000505
506 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000507
Rafael Espindola699281c2016-05-18 11:58:50 +0000508 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000509
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000510 IsCpRestoreSet = false;
511 CpRestoreOffset = -1;
512
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000513 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000514 if ((TheTriple.getArch() == Triple::mips) ||
515 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000516 IsLittleEndian = false;
517 else
518 IsLittleEndian = true;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000519
520 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
521 report_fatal_error("microMIPS64R6 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000522 }
523
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000524 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
525 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
526
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000527 bool isGP64bit() const {
528 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
529 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000530
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000531 bool isFP64bit() const {
532 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
533 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000534
Eric Christophera5762812015-01-26 17:33:46 +0000535 const MipsABIInfo &getABI() const { return ABI; }
536 bool isABI_N32() const { return ABI.IsN32(); }
537 bool isABI_N64() const { return ABI.IsN64(); }
538 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000539 bool isABI_FPXX() const {
540 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
541 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000542
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000543 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000545 }
546
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000547 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000549 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000550
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000551 bool hasMips1() const {
552 return getSTI().getFeatureBits()[Mips::FeatureMips1];
553 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000554
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000555 bool hasMips2() const {
556 return getSTI().getFeatureBits()[Mips::FeatureMips2];
557 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000558
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000559 bool hasMips3() const {
560 return getSTI().getFeatureBits()[Mips::FeatureMips3];
561 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000562
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000563 bool hasMips4() const {
564 return getSTI().getFeatureBits()[Mips::FeatureMips4];
565 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000566
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000567 bool hasMips5() const {
568 return getSTI().getFeatureBits()[Mips::FeatureMips5];
569 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000570
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000571 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000572 return getSTI().getFeatureBits()[Mips::FeatureMips32];
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 hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 return getSTI().getFeatureBits()[Mips::FeatureMips64];
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 hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000581 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000582
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000583 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000585 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000586
Daniel Sanders17793142015-02-18 16:24:50 +0000587 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
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 hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000592 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
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 hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000598
Daniel Sanders17793142015-02-18 16:24:50 +0000599 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000602
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000603 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000606
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000607 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000608 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000609 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000610
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000611 bool hasDSP() const {
612 return getSTI().getFeatureBits()[Mips::FeatureDSP];
613 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000614
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000615 bool hasDSPR2() const {
616 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
617 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000618
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000619 bool hasDSPR3() const {
620 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000622
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000623 bool hasMSA() const {
624 return getSTI().getFeatureBits()[Mips::FeatureMSA];
625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000626
Kai Nackee0245392015-01-27 19:11:28 +0000627 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000628 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000629 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000630
Daniel Sandersa6994442015-08-18 12:33:54 +0000631 bool inPicMode() {
632 return IsPicEnabled;
633 }
634
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000635 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000636 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000637 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000638
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000639 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000640 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000641 }
642
Eric Christophere8ae3e32015-05-07 23:10:21 +0000643 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000644 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000645 }
Simon Dardisae719c52017-07-11 18:03:20 +0000646 bool hasMT() const {
647 return getSTI().getFeatureBits()[Mips::FeatureMT];
648 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000649
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000650 bool hasCRC() const {
651 return getSTI().getFeatureBits()[Mips::FeatureCRC];
652 }
653
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000654 bool hasVirt() const {
655 return getSTI().getFeatureBits()[Mips::FeatureVirt];
656 }
657
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000658 bool hasGINV() const {
659 return getSTI().getFeatureBits()[Mips::FeatureGINV];
660 }
661
Toma Tabacud9d344b2015-04-27 14:05:04 +0000662 /// Warn if RegIndex is the same as the current AT.
663 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000664
665 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000666
667 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000668
669 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
670 AsmToken::TokenKind OperatorToken,
671 MCContext &Ctx) override {
672 switch(OperatorToken) {
673 default:
674 llvm_unreachable("Unknown token");
675 return nullptr;
676 case AsmToken::PercentCall16:
677 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
678 case AsmToken::PercentCall_Hi:
679 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
680 case AsmToken::PercentCall_Lo:
681 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
682 case AsmToken::PercentDtprel_Hi:
683 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
684 case AsmToken::PercentDtprel_Lo:
685 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
686 case AsmToken::PercentGot:
687 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
688 case AsmToken::PercentGot_Disp:
689 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
690 case AsmToken::PercentGot_Hi:
691 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
692 case AsmToken::PercentGot_Lo:
693 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
694 case AsmToken::PercentGot_Ofst:
695 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
696 case AsmToken::PercentGot_Page:
697 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
698 case AsmToken::PercentGottprel:
699 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
700 case AsmToken::PercentGp_Rel:
701 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
702 case AsmToken::PercentHi:
703 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
704 case AsmToken::PercentHigher:
705 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
706 case AsmToken::PercentHighest:
707 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
708 case AsmToken::PercentLo:
709 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
710 case AsmToken::PercentNeg:
711 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
712 case AsmToken::PercentPcrel_Hi:
713 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
714 case AsmToken::PercentPcrel_Lo:
715 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
716 case AsmToken::PercentTlsgd:
717 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
718 case AsmToken::PercentTlsldm:
719 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
720 case AsmToken::PercentTprel_Hi:
721 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
722 case AsmToken::PercentTprel_Lo:
723 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
724 }
725 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000726};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000727
728/// MipsOperand - Instances of this class represent a parsed Mips machine
729/// instruction.
730class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000731public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 /// Broad categories of register classes
733 /// The exact class is finalized by the render method.
734 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000735 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000736 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000737 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 RegKind_FCC = 4, /// FCC
739 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
740 RegKind_MSACtrl = 16, /// MSA control registers
741 RegKind_COP2 = 32, /// COP2
742 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
743 /// context).
744 RegKind_CCR = 128, /// CCR
745 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000746 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000747 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000748 /// Potentially any (e.g. $1)
749 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
750 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000751 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000752 };
753
754private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000755 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000756 k_Immediate, /// An immediate (possibly involving symbol references)
757 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000758 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000759 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000760 k_RegList, /// A physical register list
761 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000762 } Kind;
763
David Blaikie960ea3f2014-06-08 16:18:35 +0000764public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 MipsOperand(KindTy K, MipsAsmParser &Parser)
766 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
767
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000768 ~MipsOperand() override {
769 switch (Kind) {
770 case k_Immediate:
771 break;
772 case k_Memory:
773 delete Mem.Base;
774 break;
775 case k_RegList:
776 delete RegList.List;
777 case k_RegisterIndex:
778 case k_Token:
779 case k_RegPair:
780 break;
781 }
782 }
783
David Blaikie960ea3f2014-06-08 16:18:35 +0000784private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 /// For diagnostics, and checking the assembler temporary
786 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000787
Eric Christopher8996c5d2013-03-15 00:42:55 +0000788 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000789 const char *Data;
790 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000791 };
792
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 struct RegIdxOp {
794 unsigned Index; /// Index into the register class
795 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000796 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000797 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000798 };
799
800 struct ImmOp {
801 const MCExpr *Val;
802 };
803
804 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000806 const MCExpr *Off;
807 };
808
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000809 struct RegListOp {
810 SmallVector<unsigned, 10> *List;
811 };
812
Jack Carterb4dbc172012-09-05 23:34:03 +0000813 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000814 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000816 struct ImmOp Imm;
817 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000818 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000819 };
820
821 SMLoc StartLoc, EndLoc;
822
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000824 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
825 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000826 const MCRegisterInfo *RegInfo,
827 SMLoc S, SMLoc E,
828 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000829 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 Op->RegIdx.Index = Index;
831 Op->RegIdx.RegInfo = RegInfo;
832 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000833 Op->RegIdx.Tok.Data = Str.data();
834 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 Op->StartLoc = S;
836 Op->EndLoc = E;
837 return Op;
838 }
839
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000840public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 /// Coerce the register to GPR32 and return the real register for the current
842 /// target.
843 unsigned getGPR32Reg() const {
844 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000845 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000846 unsigned ClassID = Mips::GPR32RegClassID;
847 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000848 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000849
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000850 /// Coerce the register to GPR32 and return the real register for the current
851 /// target.
852 unsigned getGPRMM16Reg() const {
853 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
854 unsigned ClassID = Mips::GPR32RegClassID;
855 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
856 }
857
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 /// Coerce the register to GPR64 and return the real register for the current
859 /// target.
860 unsigned getGPR64Reg() const {
861 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
862 unsigned ClassID = Mips::GPR64RegClassID;
863 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000864 }
865
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000866private:
867 /// Coerce the register to AFGR64 and return the real register for the current
868 /// target.
869 unsigned getAFGR64Reg() const {
870 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
871 if (RegIdx.Index % 2 != 0)
872 AsmParser.Warning(StartLoc, "Float register should be even.");
873 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
874 .getRegister(RegIdx.Index / 2);
875 }
876
877 /// Coerce the register to FGR64 and return the real register for the current
878 /// target.
879 unsigned getFGR64Reg() const {
880 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
881 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
882 .getRegister(RegIdx.Index);
883 }
884
885 /// Coerce the register to FGR32 and return the real register for the current
886 /// target.
887 unsigned getFGR32Reg() const {
888 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
889 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
890 .getRegister(RegIdx.Index);
891 }
892
893 /// Coerce the register to FGRH32 and return the real register for the current
894 /// target.
895 unsigned getFGRH32Reg() const {
896 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
897 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
898 .getRegister(RegIdx.Index);
899 }
900
901 /// Coerce the register to FCC and return the real register for the current
902 /// target.
903 unsigned getFCCReg() const {
904 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
905 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
906 .getRegister(RegIdx.Index);
907 }
908
909 /// Coerce the register to MSA128 and return the real register for the current
910 /// target.
911 unsigned getMSA128Reg() const {
912 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
913 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
914 // identical
915 unsigned ClassID = Mips::MSA128BRegClassID;
916 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
917 }
918
919 /// Coerce the register to MSACtrl and return the real register for the
920 /// current target.
921 unsigned getMSACtrlReg() const {
922 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
923 unsigned ClassID = Mips::MSACtrlRegClassID;
924 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
925 }
926
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000927 /// Coerce the register to COP0 and return the real register for the
928 /// current target.
929 unsigned getCOP0Reg() const {
930 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
931 unsigned ClassID = Mips::COP0RegClassID;
932 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
933 }
934
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 /// Coerce the register to COP2 and return the real register for the
936 /// current target.
937 unsigned getCOP2Reg() const {
938 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
939 unsigned ClassID = Mips::COP2RegClassID;
940 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
941 }
942
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000943 /// Coerce the register to COP3 and return the real register for the
944 /// current target.
945 unsigned getCOP3Reg() const {
946 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
947 unsigned ClassID = Mips::COP3RegClassID;
948 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
949 }
950
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 /// Coerce the register to ACC64DSP and return the real register for the
952 /// current target.
953 unsigned getACC64DSPReg() const {
954 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
955 unsigned ClassID = Mips::ACC64DSPRegClassID;
956 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
957 }
958
959 /// Coerce the register to HI32DSP and return the real register for the
960 /// current target.
961 unsigned getHI32DSPReg() const {
962 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
963 unsigned ClassID = Mips::HI32DSPRegClassID;
964 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
965 }
966
967 /// Coerce the register to LO32DSP and return the real register for the
968 /// current target.
969 unsigned getLO32DSPReg() const {
970 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
971 unsigned ClassID = Mips::LO32DSPRegClassID;
972 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
973 }
974
975 /// Coerce the register to CCR and return the real register for the
976 /// current target.
977 unsigned getCCRReg() const {
978 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
979 unsigned ClassID = Mips::CCRRegClassID;
980 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
981 }
982
983 /// Coerce the register to HWRegs and return the real register for the
984 /// current target.
985 unsigned getHWRegsReg() const {
986 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
987 unsigned ClassID = Mips::HWRegsRegClassID;
988 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
989 }
990
991public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000992 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000993 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000994 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000996 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000997 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000998 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000999 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001000 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001001
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 void addRegOperands(MCInst &Inst, unsigned N) const {
1003 llvm_unreachable("Use a custom parser instead");
1004 }
1005
Daniel Sanders21bce302014-04-01 12:35:23 +00001006 /// Render the operand to an MCInst as a GPR32
1007 /// Asserts if the wrong number of operands are requested, or the operand
1008 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +00001009 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
1011 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1012 }
1013
1014 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
1016 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1017 }
1018
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001019 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001021 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 }
1023
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001024 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001026 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001027 }
1028
Jozef Kolek1904fa22014-11-24 14:25:53 +00001029 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001031 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001032 }
1033
Zoran Jovanovic41688672015-02-10 16:36:20 +00001034 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1035 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001036 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001037 }
1038
Daniel Sanders21bce302014-04-01 12:35:23 +00001039 /// Render the operand to an MCInst as a GPR64
1040 /// Asserts if the wrong number of operands are requested, or the operand
1041 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001044 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 }
1046
1047 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001049 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 }
1051
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001052 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1053 assert(N == 1 && "Invalid number of operands!");
1054 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1055 }
1056
1057 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1058 assert(N == 1 && "Invalid number of operands!");
1059 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1060 }
1061
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001064 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 }
1066
1067 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001069 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001070 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001071 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001072 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001073 AsmParser.getParser().printError(
1074 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1075 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001076 }
1077
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001078 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
1080 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1081 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1082 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1083 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1084 "registers");
1085 }
1086
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001087 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001089 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001090 }
1091
1092 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001094 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 }
1096
1097 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 }
1101
1102 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001104 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 }
1106
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001107 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1110 }
1111
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001114 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 }
1116
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001117 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001119 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001120 }
1121
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1123 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001124 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001125 }
1126
1127 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001129 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 }
1131
1132 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001134 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 }
1136
1137 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1138 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001139 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 }
1141
1142 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1143 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001144 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001145 }
1146
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001147 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001148 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001150 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001151 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001152 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001153 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001154 Inst.addOperand(MCOperand::createImm(Imm));
1155 }
1156
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001157 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001158 void addSImmOperands(MCInst &Inst, unsigned N) const {
1159 if (isImm() && !isConstantImm()) {
1160 addExpr(Inst, getImm());
1161 return;
1162 }
1163 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1164 }
1165
1166 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001167 void addUImmOperands(MCInst &Inst, unsigned N) const {
1168 if (isImm() && !isConstantImm()) {
1169 addExpr(Inst, getImm());
1170 return;
1171 }
1172 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1173 }
1174
Daniel Sanders78e89022016-03-11 11:37:50 +00001175 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1176 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 int64_t Imm = getConstantImm() - Offset;
1179 Imm = SignExtend64<Bits>(Imm);
1180 Imm += Offset;
1181 Imm += AdjustOffset;
1182 Inst.addOperand(MCOperand::createImm(Imm));
1183 }
1184
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001185 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001186 assert(N == 1 && "Invalid number of operands!");
1187 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001188 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001189 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001190
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001191 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001192 assert(N == 2 && "Invalid number of operands!");
1193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001194 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1195 ? getMemBase()->getGPR64Reg()
1196 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001197
1198 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001199 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001200 }
1201
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001202 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1203 assert(N == 2 && "Invalid number of operands!");
1204
Jim Grosbache9119e42015-05-13 18:37:00 +00001205 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001206
1207 const MCExpr *Expr = getMemOff();
1208 addExpr(Inst, Expr);
1209 }
1210
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001211 void addRegListOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
1213
1214 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001215 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001216 }
1217
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001218 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1219 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001220 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001221 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001222 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1223 Inst.addOperand(MCOperand::createReg(
1224 RegIdx.RegInfo->getRegClass(
1225 AsmParser.getABI().AreGprs64bit()
1226 ? Mips::GPR64RegClassID
1227 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1228 Inst.addOperand(MCOperand::createReg(
1229 RegIdx.RegInfo->getRegClass(
1230 AsmParser.getABI().AreGprs64bit()
1231 ? Mips::GPR64RegClassID
1232 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001233 }
1234
Zoran Jovanovic41688672015-02-10 16:36:20 +00001235 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1236 assert(N == 2 && "Invalid number of operands!");
1237 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001238 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001239 }
1240
Craig Topper56c590a2014-04-29 07:58:02 +00001241 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001242 // As a special case until we sort out the definition of div/divu, accept
1243 // $0/$zero here so that MCK_ZERO works correctly.
1244 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001246
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001248 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001249
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001251 int64_t Res;
1252 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001253 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001254
Daniel Sanders52da7af2015-11-06 12:11:03 +00001255 bool isConstantImmz() const {
1256 return isConstantImm() && getConstantImm() == 0;
1257 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001258
Daniel Sandersea4f6532015-11-06 12:22:31 +00001259 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1260 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1261 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001262
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001263 template <unsigned Bits> bool isSImm() const {
1264 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1265 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001267 template <unsigned Bits> bool isUImm() const {
1268 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1269 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001270
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001271 template <unsigned Bits> bool isAnyImm() const {
1272 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1273 isUInt<Bits>(getConstantImm()))
1274 : isImm();
1275 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001276
Daniel Sanders78e89022016-03-11 11:37:50 +00001277 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1278 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001279 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001280
Hrvoje Varga46458d02016-02-25 12:53:29 +00001281 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1282 return isConstantImm() && getConstantImm() >= Bottom &&
1283 getConstantImm() <= Top;
1284 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001285
Craig Topper56c590a2014-04-29 07:58:02 +00001286 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001287 // Note: It's not possible to pretend that other operand kinds are tokens.
1288 // The matcher emitter checks tokens first.
1289 return Kind == k_Token;
1290 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001291
Craig Topper56c590a2014-04-29 07:58:02 +00001292 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001293
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001294 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001295 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001296 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001297
Simon Dardis4ccda502016-05-27 13:56:36 +00001298 // Allow relocation operators.
1299 // FIXME: This predicate and others need to look through binary expressions
1300 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001301 template <unsigned Bits, unsigned ShiftAmount = 0>
1302 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001303 if (!isMem())
1304 return false;
1305 if (!getMemBase()->isGPRAsmReg())
1306 return false;
1307 if (isa<MCTargetExpr>(getMemOff()) ||
1308 (isConstantMemOff() &&
1309 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1310 return true;
1311 MCValue Res;
1312 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1313 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001314 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001315
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001316 bool isMemWithPtrSizeOffset() const {
1317 if (!isMem())
1318 return false;
1319 if (!getMemBase()->isGPRAsmReg())
1320 return false;
1321 const unsigned PtrBits = 32;
1322 if (isa<MCTargetExpr>(getMemOff()) ||
1323 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1324 return true;
1325 MCValue Res;
1326 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1327 return IsReloc && isIntN(PtrBits, Res.getConstant());
1328 }
1329
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001330 bool isMemWithGRPMM16Base() const {
1331 return isMem() && getMemBase()->isMM16AsmReg();
1332 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001333
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001334 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1335 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1336 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1337 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001338
Jozef Kolek12c69822014-12-23 16:16:33 +00001339 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1340 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1341 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1342 && (getMemBase()->getGPR32Reg() == Mips::SP);
1343 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001344
Daniel Sanderse473dc92016-05-09 13:38:25 +00001345 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1346 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1347 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1348 && (getMemBase()->getGPR32Reg() == Mips::GP);
1349 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001350
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001351 template <unsigned Bits, unsigned ShiftLeftAmount>
1352 bool isScaledUImm() const {
1353 return isConstantImm() &&
1354 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001355 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001356
Daniel Sanders97297772016-03-22 14:40:00 +00001357 template <unsigned Bits, unsigned ShiftLeftAmount>
1358 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001359 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1360 return true;
1361 // Operand can also be a symbol or symbol plus offset in case of relocations.
1362 if (Kind != k_Immediate)
1363 return false;
1364 MCValue Res;
1365 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1366 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001367 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001368
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001369 bool isRegList16() const {
1370 if (!isRegList())
1371 return false;
1372
1373 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001374 if (Size < 2 || Size > 5)
1375 return false;
1376
1377 unsigned R0 = RegList.List->front();
1378 unsigned R1 = RegList.List->back();
1379 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1380 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001381 return false;
1382
1383 int PrevReg = *RegList.List->begin();
1384 for (int i = 1; i < Size - 1; i++) {
1385 int Reg = (*(RegList.List))[i];
1386 if ( Reg != PrevReg + 1)
1387 return false;
1388 PrevReg = Reg;
1389 }
1390
1391 return true;
1392 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001393
Vladimir Medic2b953d02013-10-01 09:48:56 +00001394 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001395
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001396 bool isLSAImm() const {
1397 if (!isConstantImm())
1398 return false;
1399 int64_t Val = getConstantImm();
1400 return 1 <= Val && Val <= 4;
1401 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001402
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001403 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001404
Zoran Jovanovic41688672015-02-10 16:36:20 +00001405 bool isMovePRegPair() const {
1406 if (Kind != k_RegList || RegList.List->size() != 2)
1407 return false;
1408
1409 unsigned R0 = RegList.List->front();
1410 unsigned R1 = RegList.List->back();
1411
1412 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1413 (R0 == Mips::A1 && R1 == Mips::A3) ||
1414 (R0 == Mips::A2 && R1 == Mips::A3) ||
1415 (R0 == Mips::A0 && R1 == Mips::S5) ||
1416 (R0 == Mips::A0 && R1 == Mips::S6) ||
1417 (R0 == Mips::A0 && R1 == Mips::A1) ||
1418 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001419 (R0 == Mips::A0 && R1 == Mips::A3) ||
1420 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1421 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1422 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1423 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1424 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1425 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1426 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1427 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001428 return true;
1429
1430 return false;
1431 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001432
1433 StringRef getToken() const {
1434 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001435 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001436 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001437
Zlatko Buljanba553a62016-05-09 08:07:28 +00001438 bool isRegPair() const {
1439 return Kind == k_RegPair && RegIdx.Index <= 30;
1440 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001441
Craig Topper56c590a2014-04-29 07:58:02 +00001442 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001443 // As a special case until we sort out the definition of div/divu, accept
1444 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001445 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1446 RegIdx.Kind & RegKind_GPR)
1447 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001448
Daniel Sanders976d9382016-07-05 13:38:40 +00001449 llvm_unreachable("Invalid access!");
1450 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001451 }
1452
Jack Carterb4dbc172012-09-05 23:34:03 +00001453 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001454 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001455 return Imm.Val;
1456 }
1457
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001458 int64_t getConstantImm() const {
1459 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001460 int64_t Value = 0;
1461 (void)Val->evaluateAsAbsolute(Value);
1462 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001463 }
1464
1465 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001466 assert((Kind == k_Memory) && "Invalid access!");
1467 return Mem.Base;
1468 }
1469
1470 const MCExpr *getMemOff() const {
1471 assert((Kind == k_Memory) && "Invalid access!");
1472 return Mem.Off;
1473 }
1474
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001475 int64_t getConstantMemOff() const {
1476 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1477 }
1478
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001479 const SmallVectorImpl<unsigned> &getRegList() const {
1480 assert((Kind == k_RegList) && "Invalid access!");
1481 return *(RegList.List);
1482 }
1483
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001484 unsigned getRegPair() const {
1485 assert((Kind == k_RegPair) && "Invalid access!");
1486 return RegIdx.Index;
1487 }
1488
David Blaikie960ea3f2014-06-08 16:18:35 +00001489 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1490 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001491 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001492 Op->Tok.Data = Str.data();
1493 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001494 Op->StartLoc = S;
1495 Op->EndLoc = S;
1496 return Op;
1497 }
1498
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001499 /// Create a numeric register (e.g. $1). The exact register remains
1500 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001501 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001502 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1503 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001504 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001505 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001506 }
1507
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001508 /// Create a register that is definitely a GPR.
1509 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001510 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001511 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1512 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1513 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001514 }
1515
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001516 /// Create a register that is definitely a FGR.
1517 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001518 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001519 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1520 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1521 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001522 }
1523
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001524 /// Create a register that is definitely a HWReg.
1525 /// This is typically only used for named registers such as $hwr_cpunum.
1526 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001527 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001528 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001529 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001530 }
1531
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001532 /// Create a register that is definitely an FCC.
1533 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001534 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001535 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1536 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1537 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001538 }
1539
1540 /// Create a register that is definitely an ACC.
1541 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001542 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001543 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1544 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1545 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001546 }
1547
1548 /// Create a register that is definitely an MSA128.
1549 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001550 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001551 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1552 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1553 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001554 }
1555
1556 /// Create a register that is definitely an MSACtrl.
1557 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001558 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001559 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1560 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1561 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001562 }
1563
David Blaikie960ea3f2014-06-08 16:18:35 +00001564 static std::unique_ptr<MipsOperand>
1565 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001566 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001567 Op->Imm.Val = Val;
1568 Op->StartLoc = S;
1569 Op->EndLoc = E;
1570 return Op;
1571 }
1572
David Blaikie960ea3f2014-06-08 16:18:35 +00001573 static std::unique_ptr<MipsOperand>
1574 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1575 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001576 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001577 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001578 Op->Mem.Off = Off;
1579 Op->StartLoc = S;
1580 Op->EndLoc = E;
1581 return Op;
1582 }
1583
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001584 static std::unique_ptr<MipsOperand>
1585 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1586 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001587 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001588
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001589 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001590 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001591 Op->StartLoc = StartLoc;
1592 Op->EndLoc = EndLoc;
1593 return Op;
1594 }
1595
Daniel Sandersd044e492016-05-09 13:10:57 +00001596 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1597 SMLoc S, SMLoc E,
1598 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001599 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001600 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001601 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1602 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001603 Op->StartLoc = S;
1604 Op->EndLoc = E;
1605 return Op;
1606 }
1607
Simon Dardis509da1a2017-02-13 16:06:48 +00001608 bool isGPRZeroAsmReg() const {
1609 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1610 }
1611
1612 bool isGPRNonZeroAsmReg() const {
1613 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1614 RegIdx.Index <= 31;
1615 }
1616
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001617 bool isGPRAsmReg() const {
1618 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001619 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001620
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001621 bool isMM16AsmReg() const {
1622 if (!(isRegIdx() && RegIdx.Kind))
1623 return false;
1624 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1625 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001626
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001627 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001628 bool isMM16AsmRegZero() const {
1629 if (!(isRegIdx() && RegIdx.Kind))
1630 return false;
1631 return (RegIdx.Index == 0 ||
1632 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1633 RegIdx.Index == 17);
1634 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001635
Zoran Jovanovic41688672015-02-10 16:36:20 +00001636 bool isMM16AsmRegMoveP() const {
1637 if (!(isRegIdx() && RegIdx.Kind))
1638 return false;
1639 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1640 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 bool isFGRAsmReg() const {
1644 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1645 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001646 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001647
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001648 bool isStrictlyFGRAsmReg() const {
1649 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1650 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1651 }
1652
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 bool isHWRegsAsmReg() const {
1654 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001655 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001656
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001657 bool isCCRAsmReg() const {
1658 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001659 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001660
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001661 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001662 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1663 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001664 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001665 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001666
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001667 bool isACCAsmReg() const {
1668 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001669 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001670
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001671 bool isCOP0AsmReg() const {
1672 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1673 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001674
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001675 bool isCOP2AsmReg() const {
1676 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001677 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001678
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001679 bool isCOP3AsmReg() const {
1680 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1681 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001682
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001683 bool isMSA128AsmReg() const {
1684 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001685 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001686
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001687 bool isMSACtrlAsmReg() const {
1688 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001689 }
1690
Jack Carterb4dbc172012-09-05 23:34:03 +00001691 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001692 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001693 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001694 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001695
Craig Topper56c590a2014-04-29 07:58:02 +00001696 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001697 switch (Kind) {
1698 case k_Immediate:
1699 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001700 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001701 OS << ">";
1702 break;
1703 case k_Memory:
1704 OS << "Mem<";
1705 Mem.Base->print(OS);
1706 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001707 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001708 OS << ">";
1709 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001710 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001711 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1712 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001713 break;
1714 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001715 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001716 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001717 case k_RegList:
1718 OS << "RegList< ";
1719 for (auto Reg : (*RegList.List))
1720 OS << Reg << " ";
1721 OS << ">";
1722 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001723 case k_RegPair:
1724 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1725 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001726 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001727 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001728
1729 bool isValidForTie(const MipsOperand &Other) const {
1730 if (Kind != Other.Kind)
1731 return false;
1732
1733 switch (Kind) {
1734 default:
1735 llvm_unreachable("Unexpected kind");
1736 return false;
1737 case k_RegisterIndex: {
1738 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1739 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1740 return Token == OtherToken;
1741 }
1742 }
1743 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001744}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001745
1746} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001747
Jack Carter9e65aa32013-03-22 00:05:30 +00001748namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001749
Jack Carter9e65aa32013-03-22 00:05:30 +00001750extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001751
1752} // end namespace llvm
1753
Jack Carter9e65aa32013-03-22 00:05:30 +00001754static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1755 return MipsInsts[Opcode];
1756}
1757
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001758static bool hasShortDelaySlot(unsigned Opcode) {
1759 switch (Opcode) {
1760 case Mips::JALS_MM:
1761 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001762 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001763 case Mips::BGEZALS_MM:
1764 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001765 return true;
1766 default:
1767 return false;
1768 }
1769}
1770
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001771static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1772 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1773 return &SRExpr->getSymbol();
1774 }
1775
1776 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1777 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1778 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1779
1780 if (LHSSym)
1781 return LHSSym;
1782
1783 if (RHSSym)
1784 return RHSSym;
1785
1786 return nullptr;
1787 }
1788
1789 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1790 return getSingleMCSymbol(UExpr->getSubExpr());
1791
1792 return nullptr;
1793}
1794
1795static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1796 if (isa<MCSymbolRefExpr>(Expr))
1797 return 1;
1798
1799 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1800 return countMCSymbolRefExpr(BExpr->getLHS()) +
1801 countMCSymbolRefExpr(BExpr->getRHS());
1802
1803 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1804 return countMCSymbolRefExpr(UExpr->getSubExpr());
1805
1806 return 0;
1807}
1808
Jack Carter9e65aa32013-03-22 00:05:30 +00001809bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001810 MCStreamer &Out,
1811 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001812 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001813 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001814 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001815
Jack Carter9e65aa32013-03-22 00:05:30 +00001816 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001817
1818 if (MCID.isBranch() || MCID.isCall()) {
1819 const unsigned Opcode = Inst.getOpcode();
1820 MCOperand Offset;
1821
1822 switch (Opcode) {
1823 default:
1824 break;
Kai Nackee0245392015-01-27 19:11:28 +00001825 case Mips::BBIT0:
1826 case Mips::BBIT032:
1827 case Mips::BBIT1:
1828 case Mips::BBIT132:
1829 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001830 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001831
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001832 case Mips::BEQ:
1833 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001834 case Mips::BEQ_MM:
1835 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001836 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001837 Offset = Inst.getOperand(2);
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;
1846 case Mips::BGEZ:
1847 case Mips::BGTZ:
1848 case Mips::BLEZ:
1849 case Mips::BLTZ:
1850 case Mips::BGEZAL:
1851 case Mips::BLTZAL:
1852 case Mips::BC1F:
1853 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001854 case Mips::BGEZ_MM:
1855 case Mips::BGTZ_MM:
1856 case Mips::BLEZ_MM:
1857 case Mips::BLTZ_MM:
1858 case Mips::BGEZAL_MM:
1859 case Mips::BLTZAL_MM:
1860 case Mips::BC1F_MM:
1861 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001862 case Mips::BC1EQZC_MMR6:
1863 case Mips::BC1NEZC_MMR6:
1864 case Mips::BC2EQZC_MMR6:
1865 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001866 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001867 Offset = Inst.getOperand(1);
1868 if (!Offset.isImm())
1869 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001870 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001871 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001872 if (OffsetToAlignment(Offset.getImm(),
1873 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001874 return Error(IDLoc, "branch to misaligned address");
1875 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001876 case Mips::BGEC: case Mips::BGEC_MMR6:
1877 case Mips::BLTC: case Mips::BLTC_MMR6:
1878 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1879 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1880 case Mips::BEQC: case Mips::BEQC_MMR6:
1881 case Mips::BNEC: case Mips::BNEC_MMR6:
1882 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1883 Offset = Inst.getOperand(2);
1884 if (!Offset.isImm())
1885 break; // We'll deal with this situation later on when applying fixups.
1886 if (!isIntN(18, Offset.getImm()))
1887 return Error(IDLoc, "branch target out of range");
1888 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1889 return Error(IDLoc, "branch to misaligned address");
1890 break;
1891 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1892 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1893 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1894 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1895 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1896 Offset = Inst.getOperand(1);
1897 if (!Offset.isImm())
1898 break; // We'll deal with this situation later on when applying fixups.
1899 if (!isIntN(18, Offset.getImm()))
1900 return Error(IDLoc, "branch target out of range");
1901 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1902 return Error(IDLoc, "branch to misaligned address");
1903 break;
1904 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1905 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1906 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1907 Offset = Inst.getOperand(1);
1908 if (!Offset.isImm())
1909 break; // We'll deal with this situation later on when applying fixups.
1910 if (!isIntN(23, Offset.getImm()))
1911 return Error(IDLoc, "branch target out of range");
1912 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1913 return Error(IDLoc, "branch to misaligned address");
1914 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001915 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001916 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001917 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001918 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001919 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1920 Offset = Inst.getOperand(1);
1921 if (!Offset.isImm())
1922 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001923 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001924 return Error(IDLoc, "branch target out of range");
1925 if (OffsetToAlignment(Offset.getImm(), 2LL))
1926 return Error(IDLoc, "branch to misaligned address");
1927 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001928 }
1929 }
1930
Daniel Sandersa84989a2014-06-16 13:25:35 +00001931 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1932 // We still accept it but it is a normal nop.
1933 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1934 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1935 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1936 "nop instruction");
1937 }
1938
Kai Nackee0245392015-01-27 19:11:28 +00001939 if (hasCnMips()) {
1940 const unsigned Opcode = Inst.getOpcode();
1941 MCOperand Opnd;
1942 int Imm;
1943
1944 switch (Opcode) {
1945 default:
1946 break;
1947
1948 case Mips::BBIT0:
1949 case Mips::BBIT032:
1950 case Mips::BBIT1:
1951 case Mips::BBIT132:
1952 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1953 // The offset is handled above
1954 Opnd = Inst.getOperand(1);
1955 if (!Opnd.isImm())
1956 return Error(IDLoc, "expected immediate operand kind");
1957 Imm = Opnd.getImm();
1958 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1959 Opcode == Mips::BBIT1 ? 63 : 31))
1960 return Error(IDLoc, "immediate operand value out of range");
1961 if (Imm > 31) {
1962 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1963 : Mips::BBIT132);
1964 Inst.getOperand(1).setImm(Imm - 32);
1965 }
1966 break;
1967
Kai Nackee0245392015-01-27 19:11:28 +00001968 case Mips::SEQi:
1969 case Mips::SNEi:
1970 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1971 Opnd = Inst.getOperand(2);
1972 if (!Opnd.isImm())
1973 return Error(IDLoc, "expected immediate operand kind");
1974 Imm = Opnd.getImm();
1975 if (!isInt<10>(Imm))
1976 return Error(IDLoc, "immediate operand value out of range");
1977 break;
1978 }
1979 }
1980
Simon Dardis509da1a2017-02-13 16:06:48 +00001981 // Warn on division by zero. We're checking here as all instructions get
1982 // processed here, not just the macros that need expansion.
1983 //
1984 // The MIPS backend models most of the divison instructions and macros as
1985 // three operand instructions. The pre-R6 divide instructions however have
1986 // two operands and explicitly define HI/LO as part of the instruction,
1987 // not in the operands.
1988 unsigned FirstOp = 1;
1989 unsigned SecondOp = 2;
1990 switch (Inst.getOpcode()) {
1991 default:
1992 break;
1993 case Mips::SDivIMacro:
1994 case Mips::UDivIMacro:
1995 case Mips::DSDivIMacro:
1996 case Mips::DUDivIMacro:
1997 if (Inst.getOperand(2).getImm() == 0) {
1998 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1999 Inst.getOperand(1).getReg() == Mips::ZERO_64)
2000 Warning(IDLoc, "dividing zero by zero");
2001 else
2002 Warning(IDLoc, "division by zero");
2003 }
2004 break;
2005 case Mips::DSDIV:
2006 case Mips::SDIV:
2007 case Mips::UDIV:
2008 case Mips::DUDIV:
2009 case Mips::UDIV_MM:
2010 case Mips::SDIV_MM:
2011 FirstOp = 0;
2012 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00002013 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00002014 case Mips::SDivMacro:
2015 case Mips::DSDivMacro:
2016 case Mips::UDivMacro:
2017 case Mips::DUDivMacro:
2018 case Mips::DIV:
2019 case Mips::DIVU:
2020 case Mips::DDIV:
2021 case Mips::DDIVU:
2022 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002023 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002024 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
2025 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
2026 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
2027 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
2028 Warning(IDLoc, "dividing zero by zero");
2029 else
2030 Warning(IDLoc, "division by zero");
2031 }
2032 break;
2033 }
2034
Simon Atanasyan50485142016-12-12 17:40:26 +00002035 // For PIC code convert unconditional jump to unconditional branch.
2036 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2037 inPicMode()) {
2038 MCInst BInst;
2039 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2040 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2041 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2042 BInst.addOperand(Inst.getOperand(0));
2043 Inst = BInst;
2044 }
2045
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002046 // This expansion is not in a function called by tryExpandInstruction()
2047 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002048 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2049 inPicMode()) {
2050 warnIfNoMacro(IDLoc);
2051
2052 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2053
2054 // We can do this expansion if there's only 1 symbol in the argument
2055 // expression.
2056 if (countMCSymbolRefExpr(JalExpr) > 1)
2057 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2058
2059 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002060 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002061 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2062
2063 // FIXME: Add support for label+offset operands (currently causes an error).
2064 // FIXME: Add support for forward-declared local symbols.
2065 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002066 if (JalSym->isInSection() || JalSym->isTemporary() ||
2067 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002068 if (isABI_O32()) {
2069 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002070 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002071 // R_(MICRO)MIPS_GOT16 label
2072 // addiu $25, $25, 0
2073 // R_(MICRO)MIPS_LO16 label
2074 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002075 const MCExpr *Got16RelocExpr =
2076 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2077 const MCExpr *Lo16RelocExpr =
2078 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002079
Daniel Sandersa736b372016-04-29 13:33:12 +00002080 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2081 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2082 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2083 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002084 } else if (isABI_N32() || isABI_N64()) {
2085 // If it's a local symbol and the N32/N64 ABIs are being used,
2086 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002087 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002088 // R_(MICRO)MIPS_GOT_DISP label
2089 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002090 const MCExpr *GotDispRelocExpr =
2091 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002092
Daniel Sandersa736b372016-04-29 13:33:12 +00002093 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2094 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2095 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002096 }
2097 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002098 // If it's an external/weak symbol, we expand to:
2099 // lw/ld $25, 0($gp)
2100 // R_(MICRO)MIPS_CALL16 label
2101 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002102 const MCExpr *Call16RelocExpr =
2103 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002104
Daniel Sandersa736b372016-04-29 13:33:12 +00002105 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2106 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002107 }
2108
2109 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002110 if (IsCpRestoreSet && inMicroMipsMode())
2111 JalrInst.setOpcode(Mips::JALRS_MM);
2112 else
2113 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002114 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2115 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2116
2117 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2118 // This relocation is supposed to be an optimization hint for the linker
2119 // and is not necessary for correctness.
2120
2121 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002122 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002123 }
2124
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002125 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2126 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002127 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 // reference or immediate we may have to expand instructions.
2129 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002130 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002131 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2132 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002133 MCOperand &Op = Inst.getOperand(i);
2134 if (Op.isImm()) {
2135 int MemOffset = Op.getImm();
2136 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002137 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002138 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002139 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002140 }
2141 } else if (Op.isExpr()) {
2142 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002143 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002144 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002145 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002146 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002147 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002148 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002149 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002150 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002151 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002152 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002153 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002154 }
2155 }
2156 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002157 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002158 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002159
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002160 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002161 if (MCID.mayLoad()) {
2162 // Try to create 16-bit GP relative load instruction.
2163 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2164 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2165 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2166 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2167 MCOperand &Op = Inst.getOperand(i);
2168 if (Op.isImm()) {
2169 int MemOffset = Op.getImm();
2170 MCOperand &DstReg = Inst.getOperand(0);
2171 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002172 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002173 getContext().getRegisterInfo()->getRegClass(
2174 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002175 (BaseReg.getReg() == Mips::GP ||
2176 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002177
Daniel Sandersa736b372016-04-29 13:33:12 +00002178 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2179 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002180 return false;
2181 }
2182 }
2183 }
2184 } // for
2185 } // if load
2186
2187 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2188
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002189 MCOperand Opnd;
2190 int Imm;
2191
2192 switch (Inst.getOpcode()) {
2193 default:
2194 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002195 case Mips::ADDIUSP_MM:
2196 Opnd = Inst.getOperand(0);
2197 if (!Opnd.isImm())
2198 return Error(IDLoc, "expected immediate operand kind");
2199 Imm = Opnd.getImm();
2200 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2201 Imm % 4 != 0)
2202 return Error(IDLoc, "immediate operand value out of range");
2203 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002204 case Mips::SLL16_MM:
2205 case Mips::SRL16_MM:
2206 Opnd = Inst.getOperand(2);
2207 if (!Opnd.isImm())
2208 return Error(IDLoc, "expected immediate operand kind");
2209 Imm = Opnd.getImm();
2210 if (Imm < 1 || Imm > 8)
2211 return Error(IDLoc, "immediate operand value out of range");
2212 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002213 case Mips::LI16_MM:
2214 Opnd = Inst.getOperand(1);
2215 if (!Opnd.isImm())
2216 return Error(IDLoc, "expected immediate operand kind");
2217 Imm = Opnd.getImm();
2218 if (Imm < -1 || Imm > 126)
2219 return Error(IDLoc, "immediate operand value out of range");
2220 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002221 case Mips::ADDIUR2_MM:
2222 Opnd = Inst.getOperand(2);
2223 if (!Opnd.isImm())
2224 return Error(IDLoc, "expected immediate operand kind");
2225 Imm = Opnd.getImm();
2226 if (!(Imm == 1 || Imm == -1 ||
2227 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2228 return Error(IDLoc, "immediate operand value out of range");
2229 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002230 case Mips::ANDI16_MM:
2231 Opnd = Inst.getOperand(2);
2232 if (!Opnd.isImm())
2233 return Error(IDLoc, "expected immediate operand kind");
2234 Imm = Opnd.getImm();
2235 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2236 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2237 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2238 return Error(IDLoc, "immediate operand value out of range");
2239 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002240 case Mips::LBU16_MM:
2241 Opnd = Inst.getOperand(2);
2242 if (!Opnd.isImm())
2243 return Error(IDLoc, "expected immediate operand kind");
2244 Imm = Opnd.getImm();
2245 if (Imm < -1 || Imm > 14)
2246 return Error(IDLoc, "immediate operand value out of range");
2247 break;
2248 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002249 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002250 Opnd = Inst.getOperand(2);
2251 if (!Opnd.isImm())
2252 return Error(IDLoc, "expected immediate operand kind");
2253 Imm = Opnd.getImm();
2254 if (Imm < 0 || Imm > 15)
2255 return Error(IDLoc, "immediate operand value out of range");
2256 break;
2257 case Mips::LHU16_MM:
2258 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002259 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002260 Opnd = Inst.getOperand(2);
2261 if (!Opnd.isImm())
2262 return Error(IDLoc, "expected immediate operand kind");
2263 Imm = Opnd.getImm();
2264 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2265 return Error(IDLoc, "immediate operand value out of range");
2266 break;
2267 case Mips::LW16_MM:
2268 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002269 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002270 Opnd = Inst.getOperand(2);
2271 if (!Opnd.isImm())
2272 return Error(IDLoc, "expected immediate operand kind");
2273 Imm = Opnd.getImm();
2274 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2275 return Error(IDLoc, "immediate operand value out of range");
2276 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002277 case Mips::ADDIUPC_MM:
2278 MCOperand Opnd = Inst.getOperand(1);
2279 if (!Opnd.isImm())
2280 return Error(IDLoc, "expected immediate operand kind");
2281 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002282 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002283 return Error(IDLoc, "immediate operand value out of range");
2284 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002285 }
2286 }
2287
Daniel Sandersd8c07762016-04-18 12:35:36 +00002288 bool FillDelaySlot =
2289 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2290 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002291 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002292
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002293 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002294 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002295 switch (ExpandResult) {
2296 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002297 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002298 break;
2299 case MER_Success:
2300 break;
2301 case MER_Fail:
2302 return true;
2303 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002304
Daniel Sanderscda908a2016-05-16 09:10:13 +00002305 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2306 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002307 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002308 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002309 TOut.updateABIInfo(*this);
2310 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002311
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002312 // If this instruction has a delay slot and .set reorder is active,
2313 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002314 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002315 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2316 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002317 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002318
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002319 if ((Inst.getOpcode() == Mips::JalOneReg ||
2320 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2321 isPicAndNotNxxAbi()) {
2322 if (IsCpRestoreSet) {
2323 // We need a NOP between the JALR and the LW:
2324 // If .set reorder has been used, we've already emitted a NOP.
2325 // If .set noreorder has been used, we need to emit a NOP at this point.
2326 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002327 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2328 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002329
2330 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002331 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002332 } else
2333 Warning(IDLoc, "no .cprestore used in PIC mode");
2334 }
2335
Jack Carter9e65aa32013-03-22 00:05:30 +00002336 return false;
2337}
2338
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002339MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002340MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2341 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002342 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002343 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002344 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002345 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002346 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002347 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002348 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002349 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002350 case Mips::LoadAddrImm64:
2351 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2352 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2353 "expected immediate operand kind");
2354
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002355 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2356 Inst.getOperand(1),
2357 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002358 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002359 ? MER_Fail
2360 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002361 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002362 case Mips::LoadAddrReg64:
2363 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2364 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2365 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2366 "expected immediate operand kind");
2367
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002368 return expandLoadAddress(Inst.getOperand(0).getReg(),
2369 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2370 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002371 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002372 ? MER_Fail
2373 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002374 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002375 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002376 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2377 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002378 case Mips::SWM_MM:
2379 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002380 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2381 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002382 case Mips::JalOneReg:
2383 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002384 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002385 case Mips::BneImm:
2386 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002387 case Mips::BEQLImmMacro:
2388 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002389 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002390 case Mips::BLT:
2391 case Mips::BLE:
2392 case Mips::BGE:
2393 case Mips::BGT:
2394 case Mips::BLTU:
2395 case Mips::BLEU:
2396 case Mips::BGEU:
2397 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002398 case Mips::BLTL:
2399 case Mips::BLEL:
2400 case Mips::BGEL:
2401 case Mips::BGTL:
2402 case Mips::BLTUL:
2403 case Mips::BLEUL:
2404 case Mips::BGEUL:
2405 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002406 case Mips::BLTImmMacro:
2407 case Mips::BLEImmMacro:
2408 case Mips::BGEImmMacro:
2409 case Mips::BGTImmMacro:
2410 case Mips::BLTUImmMacro:
2411 case Mips::BLEUImmMacro:
2412 case Mips::BGEUImmMacro:
2413 case Mips::BGTUImmMacro:
2414 case Mips::BLTLImmMacro:
2415 case Mips::BLELImmMacro:
2416 case Mips::BGELImmMacro:
2417 case Mips::BGTLImmMacro:
2418 case Mips::BLTULImmMacro:
2419 case Mips::BLEULImmMacro:
2420 case Mips::BGEULImmMacro:
2421 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002422 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002423 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002424 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002425 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2426 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002427 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002428 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002429 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2430 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002431 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002432 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002433 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2434 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002435 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002436 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002437 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2438 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002439 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002440 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2441 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002442 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002443 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002444 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002445 case Mips::PseudoTRUNC_W_D:
2446 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2447 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002448
2449 case Mips::LoadImmSingleGPR:
2450 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2451 ? MER_Fail
2452 : MER_Success;
2453 case Mips::LoadImmSingleFGR:
2454 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2455 ? MER_Fail
2456 : MER_Success;
2457 case Mips::LoadImmDoubleGPR:
2458 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2459 ? MER_Fail
2460 : MER_Success;
2461 case Mips::LoadImmDoubleFGR:
2462 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2463 ? MER_Fail
2464 : MER_Success;
2465 case Mips::LoadImmDoubleFGR_32:
2466 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2467 ? MER_Fail
2468 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002469 case Mips::Ulh:
2470 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2471 case Mips::Ulhu:
2472 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002473 case Mips::Ush:
2474 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002475 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002476 case Mips::Usw:
2477 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002478 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002479 case Mips::NORImm64:
2480 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2481 case Mips::SLTImm64:
2482 if (isInt<16>(Inst.getOperand(2).getImm())) {
2483 Inst.setOpcode(Mips::SLTi64);
2484 return MER_NotAMacro;
2485 }
2486 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2487 case Mips::SLTUImm64:
2488 if (isInt<16>(Inst.getOperand(2).getImm())) {
2489 Inst.setOpcode(Mips::SLTiu64);
2490 return MER_NotAMacro;
2491 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002492 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002493 case Mips::ADDi: case Mips::ADDi_MM:
2494 case Mips::ADDiu: case Mips::ADDiu_MM:
2495 case Mips::SLTi: case Mips::SLTi_MM:
2496 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002497 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2498 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2499 int64_t ImmValue = Inst.getOperand(2).getImm();
2500 if (isInt<16>(ImmValue))
2501 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002502 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2503 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002504 }
2505 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002506 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2507 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2508 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002509 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2510 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2511 int64_t ImmValue = Inst.getOperand(2).getImm();
2512 if (isUInt<16>(ImmValue))
2513 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002514 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2515 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002516 }
2517 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002518 case Mips::ROL:
2519 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002520 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002521 case Mips::ROLImm:
2522 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002523 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002524 case Mips::DROL:
2525 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002526 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002527 case Mips::DROLImm:
2528 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002529 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002530 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002531 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002532 case Mips::MULImmMacro:
2533 case Mips::DMULImmMacro:
2534 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2535 case Mips::MULOMacro:
2536 case Mips::DMULOMacro:
2537 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2538 case Mips::MULOUMacro:
2539 case Mips::DMULOUMacro:
2540 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2541 case Mips::DMULMacro:
2542 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002543 case Mips::LDMacro:
2544 case Mips::SDMacro:
2545 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2546 Inst.getOpcode() == Mips::LDMacro)
2547 ? MER_Fail
2548 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002549 case Mips::SEQMacro:
2550 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2551 case Mips::SEQIMacro:
2552 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002553 case Mips::MFTC0: case Mips::MTTC0:
2554 case Mips::MFTGPR: case Mips::MTTGPR:
2555 case Mips::MFTLO: case Mips::MTTLO:
2556 case Mips::MFTHI: case Mips::MTTHI:
2557 case Mips::MFTACX: case Mips::MTTACX:
2558 case Mips::MFTDSP: case Mips::MTTDSP:
2559 case Mips::MFTC1: case Mips::MTTC1:
2560 case Mips::MFTHC1: case Mips::MTTHC1:
2561 case Mips::CFTC1: case Mips::CTTC1:
2562 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002563 }
Jack Carter30a59822012-10-04 04:03:53 +00002564}
Jack Carter92995f12012-10-06 00:53:28 +00002565
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002566bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002567 MCStreamer &Out,
2568 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002569 MipsTargetStreamer &TOut = getTargetStreamer();
2570
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002571 // Create a JALR instruction which is going to replace the pseudo-JAL.
2572 MCInst JalrInst;
2573 JalrInst.setLoc(IDLoc);
2574 const MCOperand FirstRegOp = Inst.getOperand(0);
2575 const unsigned Opcode = Inst.getOpcode();
2576
2577 if (Opcode == Mips::JalOneReg) {
2578 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002579 if (IsCpRestoreSet && inMicroMipsMode()) {
2580 JalrInst.setOpcode(Mips::JALRS16_MM);
2581 JalrInst.addOperand(FirstRegOp);
2582 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002583 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002584 JalrInst.addOperand(FirstRegOp);
2585 } else {
2586 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002587 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002588 JalrInst.addOperand(FirstRegOp);
2589 }
2590 } else if (Opcode == Mips::JalTwoReg) {
2591 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002592 if (IsCpRestoreSet && inMicroMipsMode())
2593 JalrInst.setOpcode(Mips::JALRS_MM);
2594 else
2595 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002596 JalrInst.addOperand(FirstRegOp);
2597 const MCOperand SecondRegOp = Inst.getOperand(1);
2598 JalrInst.addOperand(SecondRegOp);
2599 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002600 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002601
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002602 // If .set reorder is active and branch instruction has a delay slot,
2603 // emit a NOP after it.
2604 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002605 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2606 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2607 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002608
2609 return false;
2610}
2611
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002612/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002613template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002614 unsigned BitNum = findFirstSet(x);
2615
2616 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2617}
2618
2619/// Load (or add) an immediate into a register.
2620///
2621/// @param ImmValue The immediate to load.
2622/// @param DstReg The register that will hold the immediate.
2623/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2624/// for a simple initialization.
2625/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2626/// @param IsAddress True if the immediate represents an address. False if it
2627/// is an integer.
2628/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002629bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002630 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002631 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2632 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002633 MipsTargetStreamer &TOut = getTargetStreamer();
2634
Toma Tabacu00e98672015-05-01 12:19:27 +00002635 if (!Is32BitImm && !isGP64bit()) {
2636 Error(IDLoc, "instruction requires a 64-bit architecture");
2637 return true;
2638 }
2639
Daniel Sanders03f9c012015-07-14 12:24:22 +00002640 if (Is32BitImm) {
2641 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2642 // Sign extend up to 64-bit so that the predicates match the hardware
2643 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2644 // true.
2645 ImmValue = SignExtend64<32>(ImmValue);
2646 } else {
2647 Error(IDLoc, "instruction requires a 32-bit immediate");
2648 return true;
2649 }
2650 }
2651
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002652 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2653 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2654
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002655 bool UseSrcReg = false;
2656 if (SrcReg != Mips::NoRegister)
2657 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002658
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002659 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002660 if (UseSrcReg &&
2661 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002662 // At this point we need AT to perform the expansions and we exit if it is
2663 // not available.
2664 unsigned ATReg = getATReg(IDLoc);
2665 if (!ATReg)
2666 return true;
2667 TmpReg = ATReg;
2668 }
2669
Daniel Sanders03f9c012015-07-14 12:24:22 +00002670 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002671 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002672 SrcReg = ZeroReg;
2673
2674 // This doesn't quite follow the usual ABI expectations for N32 but matches
2675 // traditional assembler behaviour. N32 would normally use addiu for both
2676 // integers and addresses.
2677 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002678 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002679 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002680 }
2681
Daniel Sandersa736b372016-04-29 13:33:12 +00002682 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002683 return false;
2684 }
2685
2686 if (isUInt<16>(ImmValue)) {
2687 unsigned TmpReg = DstReg;
2688 if (SrcReg == DstReg) {
2689 TmpReg = getATReg(IDLoc);
2690 if (!TmpReg)
2691 return true;
2692 }
2693
Daniel Sandersa736b372016-04-29 13:33:12 +00002694 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002695 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002696 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002697 return false;
2698 }
2699
2700 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002701 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002702
Toma Tabacu79588102015-04-29 10:19:56 +00002703 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2704 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002705 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002706 // Traditional behaviour seems to special case this particular value. It's
2707 // not clear why other masks are handled differently.
2708 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002709 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2710 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002711 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002712 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002713 return false;
2714 }
2715
2716 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002717 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002718 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2719 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002720 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002721 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002722 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002723 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002724 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002725 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002726
Daniel Sandersa736b372016-04-29 13:33:12 +00002727 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002728 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002729 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002730 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002731 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002732 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002733 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002734
2735 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2736 if (Is32BitImm) {
2737 Error(IDLoc, "instruction requires a 32-bit immediate");
2738 return true;
2739 }
2740
2741 // Traditionally, these immediates are shifted as little as possible and as
2742 // such we align the most significant bit to bit 15 of our temporary.
2743 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2744 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2745 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2746 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002747 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2748 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002749
2750 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002751 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002752
2753 return false;
2754 }
2755
2756 warnIfNoMacro(IDLoc);
2757
2758 // The remaining case is packed with a sequence of dsll and ori with zeros
2759 // being omitted and any neighbouring dsll's being coalesced.
2760 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2761
2762 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2763 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002764 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002765 return false;
2766
2767 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2768 // skip it and defer the shift to the next chunk.
2769 unsigned ShiftCarriedForwards = 16;
2770 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2771 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2772
2773 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002774 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2775 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002776 ShiftCarriedForwards = 0;
2777 }
2778
2779 ShiftCarriedForwards += 16;
2780 }
2781 ShiftCarriedForwards -= 16;
2782
2783 // Finish any remaining shifts left by trailing zeros.
2784 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002785 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002786
2787 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002788 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002789
Matheus Almeida3813d572014-06-19 14:39:14 +00002790 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002791}
Jack Carter92995f12012-10-06 00:53:28 +00002792
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002793bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002794 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002795 const MCOperand &ImmOp = Inst.getOperand(1);
2796 assert(ImmOp.isImm() && "expected immediate operand kind");
2797 const MCOperand &DstRegOp = Inst.getOperand(0);
2798 assert(DstRegOp.isReg() && "expected register operand kind");
2799
2800 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002801 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002802 return true;
2803
2804 return false;
2805}
2806
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002807bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2808 const MCOperand &Offset,
2809 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002810 MCStreamer &Out,
2811 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002812 // la can't produce a usable address when addresses are 64-bit.
2813 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2814 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2815 // We currently can't do this because we depend on the equality
2816 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2817 Error(IDLoc, "la used to load 64-bit address");
2818 // Continue as if we had 'dla' instead.
2819 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002820 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002821 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002822
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002823 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002824 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002825 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002826 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002827 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002828
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002829 if (!Offset.isImm())
2830 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002831 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002832
Scott Egerton24557012016-01-21 15:11:01 +00002833 if (!ABI.ArePtrs64bit()) {
2834 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2835 Is32BitAddress = true;
2836 }
2837
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002838 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002839 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002840}
2841
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002842bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2843 unsigned DstReg, unsigned SrcReg,
2844 bool Is32BitSym, SMLoc IDLoc,
2845 MCStreamer &Out,
2846 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002847 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002848 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002849 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002850 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002851
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002852 if (inPicMode() && ABI.IsO32()) {
2853 MCValue Res;
2854 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2855 Error(IDLoc, "expected relocatable expression");
2856 return true;
2857 }
2858 if (Res.getSymB() != nullptr) {
2859 Error(IDLoc, "expected relocatable expression with only one symbol");
2860 return true;
2861 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002862
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002863 // The case where the result register is $25 is somewhat special. If the
2864 // symbol in the final relocation is external and not modified with a
2865 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2866 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002867 Res.getConstant() == 0 &&
2868 !(Res.getSymA()->getSymbol().isInSection() ||
2869 Res.getSymA()->getSymbol().isTemporary() ||
2870 (Res.getSymA()->getSymbol().isELF() &&
2871 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2872 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002873 const MCExpr *CallExpr =
2874 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2875 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2876 MCOperand::createExpr(CallExpr), IDLoc, STI);
2877 return false;
2878 }
2879
2880 // The remaining cases are:
2881 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2882 // >addiu $tmp, $tmp, %lo(offset)
2883 // >addiu $rd, $tmp, $rs
2884 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2885 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2886 // >addiu $rd, $tmp, $rs
2887 // The addiu's marked with a '>' may be omitted if they are redundant. If
2888 // this happens then the last instruction must use $rd as the result
2889 // register.
2890 const MipsMCExpr *GotExpr =
2891 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2892 const MCExpr *LoExpr = nullptr;
2893 if (Res.getSymA()->getSymbol().isInSection() ||
2894 Res.getSymA()->getSymbol().isTemporary())
2895 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2896 else if (Res.getConstant() != 0) {
2897 // External symbols fully resolve the symbol with just the %got(symbol)
2898 // but we must still account for any offset to the symbol for expressions
2899 // like symbol+8.
2900 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2901 }
2902
2903 unsigned TmpReg = DstReg;
2904 if (UseSrcReg &&
2905 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2906 SrcReg)) {
2907 // If $rs is the same as $rd, we need to use AT.
2908 // If it is not available we exit.
2909 unsigned ATReg = getATReg(IDLoc);
2910 if (!ATReg)
2911 return true;
2912 TmpReg = ATReg;
2913 }
2914
2915 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2916 MCOperand::createExpr(GotExpr), IDLoc, STI);
2917
2918 if (LoExpr)
2919 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2920 IDLoc, STI);
2921
2922 if (UseSrcReg)
2923 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2924
2925 return false;
2926 }
2927
Simon Dardisda96c432017-06-30 15:44:27 +00002928 if (inPicMode() && ABI.ArePtrs64bit()) {
2929 MCValue Res;
2930 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2931 Error(IDLoc, "expected relocatable expression");
2932 return true;
2933 }
2934 if (Res.getSymB() != nullptr) {
2935 Error(IDLoc, "expected relocatable expression with only one symbol");
2936 return true;
2937 }
2938
2939 // The case where the result register is $25 is somewhat special. If the
2940 // symbol in the final relocation is external and not modified with a
2941 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2942 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2943 Res.getConstant() == 0 &&
2944 !(Res.getSymA()->getSymbol().isInSection() ||
2945 Res.getSymA()->getSymbol().isTemporary() ||
2946 (Res.getSymA()->getSymbol().isELF() &&
2947 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2948 ELF::STB_LOCAL))) {
2949 const MCExpr *CallExpr =
2950 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2951 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2952 MCOperand::createExpr(CallExpr), IDLoc, STI);
2953 return false;
2954 }
2955
2956 // The remaining cases are:
2957 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2958 // >daddiu $tmp, $tmp, offset
2959 // >daddu $rd, $tmp, $rs
2960 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2961 // this happens then the last instruction must use $rd as the result
2962 // register.
2963 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2964 Res.getSymA(),
2965 getContext());
2966 const MCExpr *LoExpr = nullptr;
2967 if (Res.getConstant() != 0) {
2968 // Symbols fully resolve with just the %got_disp(symbol) but we
2969 // must still account for any offset to the symbol for
2970 // expressions like symbol+8.
2971 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2972
2973 // FIXME: Offsets greater than 16 bits are not yet implemented.
2974 // FIXME: The correct range is a 32-bit sign-extended number.
2975 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2976 Error(IDLoc, "macro instruction uses large offset, which is not "
2977 "currently supported");
2978 return true;
2979 }
2980 }
2981
2982 unsigned TmpReg = DstReg;
2983 if (UseSrcReg &&
2984 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2985 SrcReg)) {
2986 // If $rs is the same as $rd, we need to use AT.
2987 // If it is not available we exit.
2988 unsigned ATReg = getATReg(IDLoc);
2989 if (!ATReg)
2990 return true;
2991 TmpReg = ATReg;
2992 }
2993
2994 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2995 MCOperand::createExpr(GotExpr), IDLoc, STI);
2996
2997 if (LoExpr)
2998 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2999 IDLoc, STI);
3000
3001 if (UseSrcReg)
3002 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3003
3004 return false;
3005 }
3006
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003007 const MipsMCExpr *HiExpr =
3008 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3009 const MipsMCExpr *LoExpr =
3010 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00003011
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003012 // This is the 64-bit symbol address expansion.
3013 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00003014 // We need AT for the 64-bit expansion in the cases where the optional
3015 // source register is the destination register and for the superscalar
3016 // scheduled form.
3017 //
3018 // If it is not available we exit if the destination is the same as the
3019 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003020
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003021 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003022 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003023 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003024 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003025
Simon Dardis3aa8a902017-02-06 12:43:46 +00003026 bool RdRegIsRsReg =
3027 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3028
3029 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3030 unsigned ATReg = getATReg(IDLoc);
3031
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003032 // If $rs is the same as $rd:
3033 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3034 // daddiu $at, $at, %higher(sym)
3035 // dsll $at, $at, 16
3036 // daddiu $at, $at, %hi(sym)
3037 // dsll $at, $at, 16
3038 // daddiu $at, $at, %lo(sym)
3039 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003040 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3041 STI);
3042 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3043 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3044 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3045 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3046 IDLoc, STI);
3047 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3048 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3049 IDLoc, STI);
3050 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003051
3052 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003053 } else if (canUseATReg() && !RdRegIsRsReg) {
3054 unsigned ATReg = getATReg(IDLoc);
3055
3056 // If the $rs is different from $rd or if $rs isn't specified and we
3057 // have $at available:
3058 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3059 // lui $at, %hi(sym)
3060 // daddiu $rd, $rd, %higher(sym)
3061 // daddiu $at, $at, %lo(sym)
3062 // dsll32 $rd, $rd, 0
3063 // daddu $rd, $rd, $at
3064 // (daddu $rd, $rd, $rs)
3065 //
3066 // Which is preferred for superscalar issue.
3067 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3068 STI);
3069 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3070 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3071 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3072 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3073 IDLoc, STI);
3074 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3075 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3076 if (UseSrcReg)
3077 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3078
3079 return false;
3080 } else if (!canUseATReg() && !RdRegIsRsReg) {
3081 // Otherwise, synthesize the address in the destination register
3082 // serially:
3083 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3084 // daddiu $rd, $rd, %higher(sym)
3085 // dsll $rd, $rd, 16
3086 // daddiu $rd, $rd, %hi(sym)
3087 // dsll $rd, $rd, 16
3088 // daddiu $rd, $rd, %lo(sym)
3089 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3090 STI);
3091 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3092 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3093 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3094 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3095 MCOperand::createExpr(HiExpr), IDLoc, STI);
3096 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3097 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3098 MCOperand::createExpr(LoExpr), IDLoc, STI);
3099 if (UseSrcReg)
3100 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3101
3102 return false;
3103 } else {
3104 // We have a case where SrcReg == DstReg and we don't have $at
3105 // available. We can't expand this case, so error out appropriately.
3106 assert(SrcReg == DstReg && !canUseATReg() &&
3107 "Could have expanded dla but didn't?");
3108 reportParseError(IDLoc,
3109 "pseudo-instruction requires $at, which is not available");
3110 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003111 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003112 }
3113
3114 // And now, the 32-bit symbol address expansion:
3115 // If $rs is the same as $rd:
3116 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3117 // ori $at, $at, %lo(sym)
3118 // addu $rd, $at, $rd
3119 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3120 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3121 // ori $rd, $rd, %lo(sym)
3122 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003123 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003124 if (UseSrcReg &&
3125 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003126 // If $rs is the same as $rd, we need to use AT.
3127 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003128 unsigned ATReg = getATReg(IDLoc);
3129 if (!ATReg)
3130 return true;
3131 TmpReg = ATReg;
3132 }
3133
Daniel Sandersa736b372016-04-29 13:33:12 +00003134 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3135 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3136 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003137
Toma Tabacufb9d1252015-06-22 12:08:39 +00003138 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003139 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003140 else
Scott Egerton24557012016-01-21 15:11:01 +00003141 assert(
3142 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003143
Toma Tabacu674825c2015-06-16 12:16:24 +00003144 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003145}
3146
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003147// Each double-precision register DO-D15 overlaps with two of the single
3148// precision registers F0-F31. As an example, all of the following hold true:
3149// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3150static unsigned nextReg(unsigned Reg) {
3151 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3152 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3153 switch (Reg) {
3154 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3155 case Mips::ZERO: return Mips::AT;
3156 case Mips::AT: return Mips::V0;
3157 case Mips::V0: return Mips::V1;
3158 case Mips::V1: return Mips::A0;
3159 case Mips::A0: return Mips::A1;
3160 case Mips::A1: return Mips::A2;
3161 case Mips::A2: return Mips::A3;
3162 case Mips::A3: return Mips::T0;
3163 case Mips::T0: return Mips::T1;
3164 case Mips::T1: return Mips::T2;
3165 case Mips::T2: return Mips::T3;
3166 case Mips::T3: return Mips::T4;
3167 case Mips::T4: return Mips::T5;
3168 case Mips::T5: return Mips::T6;
3169 case Mips::T6: return Mips::T7;
3170 case Mips::T7: return Mips::S0;
3171 case Mips::S0: return Mips::S1;
3172 case Mips::S1: return Mips::S2;
3173 case Mips::S2: return Mips::S3;
3174 case Mips::S3: return Mips::S4;
3175 case Mips::S4: return Mips::S5;
3176 case Mips::S5: return Mips::S6;
3177 case Mips::S6: return Mips::S7;
3178 case Mips::S7: return Mips::T8;
3179 case Mips::T8: return Mips::T9;
3180 case Mips::T9: return Mips::K0;
3181 case Mips::K0: return Mips::K1;
3182 case Mips::K1: return Mips::GP;
3183 case Mips::GP: return Mips::SP;
3184 case Mips::SP: return Mips::FP;
3185 case Mips::FP: return Mips::RA;
3186 case Mips::RA: return Mips::ZERO;
3187 case Mips::D0: return Mips::F1;
3188 case Mips::D1: return Mips::F3;
3189 case Mips::D2: return Mips::F5;
3190 case Mips::D3: return Mips::F7;
3191 case Mips::D4: return Mips::F9;
3192 case Mips::D5: return Mips::F11;
3193 case Mips::D6: return Mips::F13;
3194 case Mips::D7: return Mips::F15;
3195 case Mips::D8: return Mips::F17;
3196 case Mips::D9: return Mips::F19;
3197 case Mips::D10: return Mips::F21;
3198 case Mips::D11: return Mips::F23;
3199 case Mips::D12: return Mips::F25;
3200 case Mips::D13: return Mips::F27;
3201 case Mips::D14: return Mips::F29;
3202 case Mips::D15: return Mips::F31;
3203 }
3204}
3205
3206// FIXME: This method is too general. In principle we should compute the number
3207// of instructions required to synthesize the immediate inline compared to
3208// synthesizing the address inline and relying on non .text sections.
3209// For static O32 and N32 this may yield a small benefit, for static N64 this is
3210// likely to yield a much larger benefit as we have to synthesize a 64bit
3211// address to load a 64 bit value.
3212bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3213 MCSymbol *Sym) {
3214 unsigned ATReg = getATReg(IDLoc);
3215 if (!ATReg)
3216 return true;
3217
3218 if(IsPicEnabled) {
3219 const MCExpr *GotSym =
3220 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3221 const MipsMCExpr *GotExpr =
3222 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3223
3224 if(isABI_O32() || isABI_N32()) {
3225 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3226 IDLoc, STI);
3227 } else { //isABI_N64()
3228 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3229 IDLoc, STI);
3230 }
3231 } else { //!IsPicEnabled
3232 const MCExpr *HiSym =
3233 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3234 const MipsMCExpr *HiExpr =
3235 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3236
3237 // FIXME: This is technically correct but gives a different result to gas,
3238 // but gas is incomplete there (it has a fixme noting it doesn't work with
3239 // 64-bit addresses).
3240 // FIXME: With -msym32 option, the address expansion for N64 should probably
3241 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3242 // symbol's value is considered sign extended.
3243 if(isABI_O32() || isABI_N32()) {
3244 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3245 } else { //isABI_N64()
3246 const MCExpr *HighestSym =
3247 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3248 const MipsMCExpr *HighestExpr =
3249 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3250 const MCExpr *HigherSym =
3251 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3252 const MipsMCExpr *HigherExpr =
3253 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3254
3255 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3256 STI);
3257 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3258 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3259 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3260 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3261 IDLoc, STI);
3262 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3263 }
3264 }
3265 return false;
3266}
3267
3268bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3269 bool Is64FPU, SMLoc IDLoc,
3270 MCStreamer &Out,
3271 const MCSubtargetInfo *STI) {
3272 MipsTargetStreamer &TOut = getTargetStreamer();
3273 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3274 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3275 "Invalid instruction operand.");
3276
3277 unsigned FirstReg = Inst.getOperand(0).getReg();
3278 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3279
3280 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3281 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3282 // exponent field), convert it to double (e.g. 1 to 1.0)
3283 if ((HiImmOp64 & 0x7ff00000) == 0) {
3284 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3285 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3286 }
3287
3288 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3289 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3290
3291 if (IsSingle) {
3292 // Conversion of a double in an uint64_t to a float in a uint32_t,
3293 // retaining the bit pattern of a float.
3294 uint32_t ImmOp32;
3295 double doubleImm = BitsToDouble(ImmOp64);
3296 float tmp_float = static_cast<float>(doubleImm);
3297 ImmOp32 = FloatToBits(tmp_float);
3298
3299 if (IsGPR) {
3300 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3301 Out, STI))
3302 return true;
3303 return false;
3304 } else {
3305 unsigned ATReg = getATReg(IDLoc);
3306 if (!ATReg)
3307 return true;
3308 if (LoImmOp64 == 0) {
3309 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3310 Out, STI))
3311 return true;
3312 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3313 return false;
3314 }
3315
3316 MCSection *CS = getStreamer().getCurrentSectionOnly();
3317 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3318 // where appropriate.
3319 MCSection *ReadOnlySection = getContext().getELFSection(
3320 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3321
3322 MCSymbol *Sym = getContext().createTempSymbol();
3323 const MCExpr *LoSym =
3324 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3325 const MipsMCExpr *LoExpr =
3326 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3327
3328 getStreamer().SwitchSection(ReadOnlySection);
3329 getStreamer().EmitLabel(Sym, IDLoc);
3330 getStreamer().EmitIntValue(ImmOp32, 4);
3331 getStreamer().SwitchSection(CS);
3332
3333 if(emitPartialAddress(TOut, IDLoc, Sym))
3334 return true;
3335 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3336 MCOperand::createExpr(LoExpr), IDLoc, STI);
3337 }
3338 return false;
3339 }
3340
3341 // if(!IsSingle)
3342 unsigned ATReg = getATReg(IDLoc);
3343 if (!ATReg)
3344 return true;
3345
3346 if (IsGPR) {
3347 if (LoImmOp64 == 0) {
3348 if(isABI_N32() || isABI_N64()) {
3349 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3350 IDLoc, Out, STI))
3351 return true;
3352 return false;
3353 } else {
3354 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3355 IDLoc, Out, STI))
3356 return true;
3357
3358 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3359 IDLoc, Out, STI))
3360 return true;
3361 return false;
3362 }
3363 }
3364
3365 MCSection *CS = getStreamer().getCurrentSectionOnly();
3366 MCSection *ReadOnlySection = getContext().getELFSection(
3367 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3368
3369 MCSymbol *Sym = getContext().createTempSymbol();
3370 const MCExpr *LoSym =
3371 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3372 const MipsMCExpr *LoExpr =
3373 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3374
3375 getStreamer().SwitchSection(ReadOnlySection);
3376 getStreamer().EmitLabel(Sym, IDLoc);
3377 getStreamer().EmitIntValue(HiImmOp64, 4);
3378 getStreamer().EmitIntValue(LoImmOp64, 4);
3379 getStreamer().SwitchSection(CS);
3380
3381 if(emitPartialAddress(TOut, IDLoc, Sym))
3382 return true;
3383 if(isABI_N64())
3384 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3385 MCOperand::createExpr(LoExpr), IDLoc, STI);
3386 else
3387 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3388 MCOperand::createExpr(LoExpr), IDLoc, STI);
3389
3390 if(isABI_N32() || isABI_N64())
3391 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3392 else {
3393 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3394 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3395 }
3396 return false;
3397 } else { // if(!IsGPR && !IsSingle)
3398 if ((LoImmOp64 == 0) &&
3399 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3400 // FIXME: In the case where the constant is zero, we can load the
3401 // register directly from the zero register.
3402 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3403 Out, STI))
3404 return true;
3405 if (isABI_N32() || isABI_N64())
3406 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3407 else if (hasMips32r2()) {
3408 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3409 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3410 } else {
3411 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3412 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3413 }
3414 return false;
3415 }
3416
3417 MCSection *CS = getStreamer().getCurrentSectionOnly();
3418 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3419 // where appropriate.
3420 MCSection *ReadOnlySection = getContext().getELFSection(
3421 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3422
3423 MCSymbol *Sym = getContext().createTempSymbol();
3424 const MCExpr *LoSym =
3425 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3426 const MipsMCExpr *LoExpr =
3427 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3428
3429 getStreamer().SwitchSection(ReadOnlySection);
3430 getStreamer().EmitLabel(Sym, IDLoc);
3431 getStreamer().EmitIntValue(HiImmOp64, 4);
3432 getStreamer().EmitIntValue(LoImmOp64, 4);
3433 getStreamer().SwitchSection(CS);
3434
3435 if(emitPartialAddress(TOut, IDLoc, Sym))
3436 return true;
3437 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3438 MCOperand::createExpr(LoExpr), IDLoc, STI);
3439 }
3440 return false;
3441}
3442
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003443bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3444 MCStreamer &Out,
3445 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003446 MipsTargetStreamer &TOut = getTargetStreamer();
3447
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003448 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3449 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003450
3451 MCOperand Offset = Inst.getOperand(0);
3452 if (Offset.isExpr()) {
3453 Inst.clear();
3454 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003455 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3456 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3457 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003458 } else {
3459 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003460 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003461 // If offset fits into 11 bits then this instruction becomes microMIPS
3462 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003463 if (inMicroMipsMode())
3464 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003465 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003466 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003467 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003468 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003469 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003470 Inst.clear();
3471 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003472 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3473 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3474 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003475 }
3476 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003477 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003478
Zoran Jovanovicada70912015-09-07 11:56:37 +00003479 // If .set reorder is active and branch instruction has a delay slot,
3480 // emit a NOP after it.
3481 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3482 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003483 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003484
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003485 return false;
3486}
3487
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003488bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3489 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003490 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003491 const MCOperand &DstRegOp = Inst.getOperand(0);
3492 assert(DstRegOp.isReg() && "expected register operand kind");
3493
3494 const MCOperand &ImmOp = Inst.getOperand(1);
3495 assert(ImmOp.isImm() && "expected immediate operand kind");
3496
3497 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003498 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3499 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003500
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003501 bool IsLikely = false;
3502
Toma Tabacue1e460d2015-06-11 10:36:10 +00003503 unsigned OpCode = 0;
3504 switch(Inst.getOpcode()) {
3505 case Mips::BneImm:
3506 OpCode = Mips::BNE;
3507 break;
3508 case Mips::BeqImm:
3509 OpCode = Mips::BEQ;
3510 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003511 case Mips::BEQLImmMacro:
3512 OpCode = Mips::BEQL;
3513 IsLikely = true;
3514 break;
3515 case Mips::BNELImmMacro:
3516 OpCode = Mips::BNEL;
3517 IsLikely = true;
3518 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003519 default:
3520 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3521 break;
3522 }
3523
3524 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003525 if (ImmValue == 0) {
3526 if (IsLikely) {
3527 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3528 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3529 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3530 } else
3531 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3532 STI);
3533 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003534 warnIfNoMacro(IDLoc);
3535
3536 unsigned ATReg = getATReg(IDLoc);
3537 if (!ATReg)
3538 return true;
3539
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003540 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003541 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003542 return true;
3543
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003544 if (IsLikely) {
3545 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3546 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3547 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3548 } else
3549 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003550 }
3551 return false;
3552}
3553
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003554void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003555 const MCSubtargetInfo *STI, bool IsLoad,
3556 bool IsImmOpnd) {
3557 if (IsLoad) {
3558 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3559 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003560 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003561 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3562}
3563
3564void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3565 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3566 MipsTargetStreamer &TOut = getTargetStreamer();
3567
3568 unsigned DstReg = Inst.getOperand(0).getReg();
3569 unsigned BaseReg = Inst.getOperand(1).getReg();
3570
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003571 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003572 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3573 unsigned DstRegClassID =
3574 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3575 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3576 (DstRegClassID == Mips::GPR64RegClassID);
3577
3578 if (IsImmOpnd) {
3579 // Try to use DstReg as the temporary.
3580 if (IsGPR && (BaseReg != DstReg)) {
3581 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3582 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3583 STI);
3584 return;
3585 }
3586
Matheus Almeida7de68e72014-06-18 14:46:05 +00003587 // At this point we need AT to perform the expansions and we exit if it is
3588 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003589 unsigned ATReg = getATReg(IDLoc);
3590 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003591 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003592
3593 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3594 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3595 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003596 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003597
Daniel Sandersfba875f2016-04-29 13:43:45 +00003598 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003599 MCOperand LoOperand = MCOperand::createExpr(
3600 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3601 MCOperand HiOperand = MCOperand::createExpr(
3602 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003603
3604 // Try to use DstReg as the temporary.
3605 if (IsGPR && (BaseReg != DstReg)) {
3606 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3607 LoOperand, DstReg, IDLoc, STI);
3608 return;
3609 }
3610
3611 // At this point we need AT to perform the expansions and we exit if it is
3612 // not available.
3613 unsigned ATReg = getATReg(IDLoc);
3614 if (!ATReg)
3615 return;
3616
3617 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3618 LoOperand, ATReg, IDLoc, STI);
3619}
3620
3621void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3622 const MCSubtargetInfo *STI,
3623 bool IsImmOpnd) {
3624 MipsTargetStreamer &TOut = getTargetStreamer();
3625
3626 unsigned SrcReg = Inst.getOperand(0).getReg();
3627 unsigned BaseReg = Inst.getOperand(1).getReg();
3628
Daniel Sanders241c6792016-05-12 14:01:50 +00003629 if (IsImmOpnd) {
3630 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3631 Inst.getOperand(2).getImm(),
3632 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3633 return;
3634 }
3635
Daniel Sandersfba875f2016-04-29 13:43:45 +00003636 unsigned ATReg = getATReg(IDLoc);
3637 if (!ATReg)
3638 return;
3639
Daniel Sandersfba875f2016-04-29 13:43:45 +00003640 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003641 MCOperand LoOperand = MCOperand::createExpr(
3642 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3643 MCOperand HiOperand = MCOperand::createExpr(
3644 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003645 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3646 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003647}
3648
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003649bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3650 MCStreamer &Out,
3651 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003652 unsigned OpNum = Inst.getNumOperands();
3653 unsigned Opcode = Inst.getOpcode();
3654 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3655
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003656 assert(Inst.getOperand(OpNum - 1).isImm() &&
3657 Inst.getOperand(OpNum - 2).isReg() &&
3658 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003659
3660 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3661 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003662 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3663 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3664 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3665 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003666 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003667 if (inMicroMipsMode() && hasMips32r6())
3668 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3669 else
3670 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3671 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003672
3673 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003674 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003675 return false;
3676}
3677
Toma Tabacu1a108322015-06-17 13:20:24 +00003678bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003679 MCStreamer &Out,
3680 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003681 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003682 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003683 unsigned PseudoOpcode = Inst.getOpcode();
3684 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003685 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003686 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3687
3688 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003689 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003690
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003691 unsigned TrgReg;
3692 if (TrgOp.isReg())
3693 TrgReg = TrgOp.getReg();
3694 else if (TrgOp.isImm()) {
3695 warnIfNoMacro(IDLoc);
3696 EmittedNoMacroWarning = true;
3697
3698 TrgReg = getATReg(IDLoc);
3699 if (!TrgReg)
3700 return true;
3701
3702 switch(PseudoOpcode) {
3703 default:
3704 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3705 case Mips::BLTImmMacro:
3706 PseudoOpcode = Mips::BLT;
3707 break;
3708 case Mips::BLEImmMacro:
3709 PseudoOpcode = Mips::BLE;
3710 break;
3711 case Mips::BGEImmMacro:
3712 PseudoOpcode = Mips::BGE;
3713 break;
3714 case Mips::BGTImmMacro:
3715 PseudoOpcode = Mips::BGT;
3716 break;
3717 case Mips::BLTUImmMacro:
3718 PseudoOpcode = Mips::BLTU;
3719 break;
3720 case Mips::BLEUImmMacro:
3721 PseudoOpcode = Mips::BLEU;
3722 break;
3723 case Mips::BGEUImmMacro:
3724 PseudoOpcode = Mips::BGEU;
3725 break;
3726 case Mips::BGTUImmMacro:
3727 PseudoOpcode = Mips::BGTU;
3728 break;
3729 case Mips::BLTLImmMacro:
3730 PseudoOpcode = Mips::BLTL;
3731 break;
3732 case Mips::BLELImmMacro:
3733 PseudoOpcode = Mips::BLEL;
3734 break;
3735 case Mips::BGELImmMacro:
3736 PseudoOpcode = Mips::BGEL;
3737 break;
3738 case Mips::BGTLImmMacro:
3739 PseudoOpcode = Mips::BGTL;
3740 break;
3741 case Mips::BLTULImmMacro:
3742 PseudoOpcode = Mips::BLTUL;
3743 break;
3744 case Mips::BLEULImmMacro:
3745 PseudoOpcode = Mips::BLEUL;
3746 break;
3747 case Mips::BGEULImmMacro:
3748 PseudoOpcode = Mips::BGEUL;
3749 break;
3750 case Mips::BGTULImmMacro:
3751 PseudoOpcode = Mips::BGTUL;
3752 break;
3753 }
3754
3755 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003756 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003757 return true;
3758 }
3759
Toma Tabacu1a108322015-06-17 13:20:24 +00003760 switch (PseudoOpcode) {
3761 case Mips::BLT:
3762 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003763 case Mips::BLTL:
3764 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003765 AcceptsEquality = false;
3766 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003767 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3768 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003769 ZeroSrcOpcode = Mips::BGTZ;
3770 ZeroTrgOpcode = Mips::BLTZ;
3771 break;
3772 case Mips::BLE:
3773 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003774 case Mips::BLEL:
3775 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003776 AcceptsEquality = true;
3777 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003778 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3779 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003780 ZeroSrcOpcode = Mips::BGEZ;
3781 ZeroTrgOpcode = Mips::BLEZ;
3782 break;
3783 case Mips::BGE:
3784 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003785 case Mips::BGEL:
3786 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003787 AcceptsEquality = true;
3788 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003789 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3790 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003791 ZeroSrcOpcode = Mips::BLEZ;
3792 ZeroTrgOpcode = Mips::BGEZ;
3793 break;
3794 case Mips::BGT:
3795 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003796 case Mips::BGTL:
3797 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003798 AcceptsEquality = false;
3799 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003800 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3801 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003802 ZeroSrcOpcode = Mips::BLTZ;
3803 ZeroTrgOpcode = Mips::BGTZ;
3804 break;
3805 default:
3806 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3807 }
3808
Toma Tabacu1a108322015-06-17 13:20:24 +00003809 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3810 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3811 if (IsSrcRegZero && IsTrgRegZero) {
3812 // FIXME: All of these Opcode-specific if's are needed for compatibility
3813 // with GAS' behaviour. However, they may not generate the most efficient
3814 // code in some circumstances.
3815 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003816 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3817 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003818 return false;
3819 }
3820 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003821 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3822 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003823 Warning(IDLoc, "branch is always taken");
3824 return false;
3825 }
3826 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003827 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3828 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003829 Warning(IDLoc, "branch is always taken");
3830 return false;
3831 }
3832 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003833 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3834 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003835 return false;
3836 }
3837 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003838 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3839 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003840 return false;
3841 }
3842 if (AcceptsEquality) {
3843 // If both registers are $0 and the pseudo-branch accepts equality, it
3844 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003845 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3846 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003847 Warning(IDLoc, "branch is always taken");
3848 return false;
3849 }
3850 // If both registers are $0 and the pseudo-branch does not accept
3851 // equality, it will never be taken, so we don't have to emit anything.
3852 return false;
3853 }
3854 if (IsSrcRegZero || IsTrgRegZero) {
3855 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3856 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3857 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3858 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3859 // the pseudo-branch will never be taken, so we don't emit anything.
3860 // This only applies to unsigned pseudo-branches.
3861 return false;
3862 }
3863 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3864 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3865 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3866 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3867 // the pseudo-branch will always be taken, so we emit an unconditional
3868 // branch.
3869 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003870 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3871 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003872 Warning(IDLoc, "branch is always taken");
3873 return false;
3874 }
3875 if (IsUnsigned) {
3876 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3877 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3878 // the pseudo-branch will be taken only when the non-zero register is
3879 // different from 0, so we emit a BNEZ.
3880 //
3881 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3882 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3883 // the pseudo-branch will be taken only when the non-zero register is
3884 // equal to 0, so we emit a BEQZ.
3885 //
3886 // Because only BLEU and BGEU branch on equality, we can use the
3887 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003888 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3889 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3890 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003891 return false;
3892 }
3893 // If we have a signed pseudo-branch and one of the registers is $0,
3894 // we can use an appropriate compare-to-zero branch. We select which one
3895 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003896 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3897 IsSrcRegZero ? TrgReg : SrcReg,
3898 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003899 return false;
3900 }
3901
3902 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3903 // expansions. If it is not available, we return.
3904 unsigned ATRegNum = getATReg(IDLoc);
3905 if (!ATRegNum)
3906 return true;
3907
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003908 if (!EmittedNoMacroWarning)
3909 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003910
3911 // SLT fits well with 2 of our 4 pseudo-branches:
3912 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3913 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3914 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3915 // This is accomplished by using a BNEZ with the result of the SLT.
3916 //
3917 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003918 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003919 // Because only BGE and BLE branch on equality, we can use the
3920 // AcceptsEquality variable to decide when to emit the BEQZ.
3921 // Note that the order of the SLT arguments doesn't change between
3922 // opposites.
3923 //
3924 // The same applies to the unsigned variants, except that SLTu is used
3925 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003926 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3927 ReverseOrderSLT ? TrgReg : SrcReg,
3928 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003929
Daniel Sandersa736b372016-04-29 13:33:12 +00003930 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3931 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3932 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3933 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003934 return false;
3935}
3936
Simon Dardis509da1a2017-02-13 16:06:48 +00003937// Expand a integer division macro.
3938//
3939// Notably we don't have to emit a warning when encountering $rt as the $zero
3940// register, or 0 as an immediate. processInstruction() has already done that.
3941//
3942// The destination register can only be $zero when expanding (S)DivIMacro or
3943// D(S)DivMacro.
3944
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003945bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3946 const MCSubtargetInfo *STI, const bool IsMips64,
3947 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003948 MipsTargetStreamer &TOut = getTargetStreamer();
3949
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003950 warnIfNoMacro(IDLoc);
3951
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003952 const MCOperand &RdRegOp = Inst.getOperand(0);
3953 assert(RdRegOp.isReg() && "expected register operand kind");
3954 unsigned RdReg = RdRegOp.getReg();
3955
3956 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003957 assert(RsRegOp.isReg() && "expected register operand kind");
3958 unsigned RsReg = RsRegOp.getReg();
3959
Simon Dardis12850ee2017-01-31 10:49:24 +00003960 unsigned RtReg;
3961 int64_t ImmValue;
3962
3963 const MCOperand &RtOp = Inst.getOperand(2);
3964 assert((RtOp.isReg() || RtOp.isImm()) &&
3965 "expected register or immediate operand kind");
3966 if (RtOp.isReg())
3967 RtReg = RtOp.getReg();
3968 else
3969 ImmValue = RtOp.getImm();
3970
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003971 unsigned DivOp;
3972 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003973 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003974
3975 if (IsMips64) {
3976 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3977 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003978 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003979 } else {
3980 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3981 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003982 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003983 }
3984
3985 bool UseTraps = useTraps();
3986
Simon Dardis12850ee2017-01-31 10:49:24 +00003987 if (RtOp.isImm()) {
3988 unsigned ATReg = getATReg(IDLoc);
3989 if (!ATReg)
3990 return true;
3991
3992 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003993 if (UseTraps)
3994 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3995 else
3996 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3997 return false;
3998 }
3999
4000 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004001 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004002 return false;
4003 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004004 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004005 return false;
4006 } else {
4007 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4008 false, Inst.getLoc(), Out, STI))
4009 return true;
4010 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
4011 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
4012 return false;
4013 }
4014 return true;
4015 }
4016
Simon Dardis509da1a2017-02-13 16:06:48 +00004017 // If the macro expansion of (d)div(u) would always trap or break, insert
4018 // the trap/break and exit. This gives a different result to GAS. GAS has
4019 // an inconsistency/missed optimization in that not all cases are handled
4020 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004021 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004022 if (UseTraps) {
4023 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004024 return false;
4025 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004026 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4027 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004028 }
4029
Simon Dardis509da1a2017-02-13 16:06:48 +00004030 // Temporary label for first branch traget
4031 MCContext &Context = TOut.getStreamer().getContext();
4032 MCSymbol *BrTarget;
4033 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004034
4035 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004036 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004037 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004038 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004039 BrTarget = Context.createTempSymbol();
4040 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4041 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004042 }
4043
Daniel Sandersa736b372016-04-29 13:33:12 +00004044 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004045
4046 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004047 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004048
4049 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004050 if (!UseTraps)
4051 TOut.getStreamer().EmitLabel(BrTarget);
4052
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004053 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004054 return false;
4055 }
4056
4057 unsigned ATReg = getATReg(IDLoc);
4058 if (!ATReg)
4059 return true;
4060
Simon Dardis509da1a2017-02-13 16:06:48 +00004061 if (!UseTraps)
4062 TOut.getStreamer().EmitLabel(BrTarget);
4063
Daniel Sandersa736b372016-04-29 13:33:12 +00004064 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004065
4066 // Temporary label for the second branch target.
4067 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4068 MCOperand LabelOpEnd =
4069 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4070
4071 // Branch to the mflo instruction.
4072 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4073
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004074 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004075 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4076 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004077 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004078 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004079 }
4080
4081 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004082 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004083 else {
4084 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004085 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004086 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4087 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004088 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004089
4090 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004091 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004092 return false;
4093}
4094
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004095bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004096 SMLoc IDLoc, MCStreamer &Out,
4097 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004098 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004099
4100 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4101 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4102 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4103
4104 unsigned FirstReg = Inst.getOperand(0).getReg();
4105 unsigned SecondReg = Inst.getOperand(1).getReg();
4106 unsigned ThirdReg = Inst.getOperand(2).getReg();
4107
4108 if (hasMips1() && !hasMips2()) {
4109 unsigned ATReg = getATReg(IDLoc);
4110 if (!ATReg)
4111 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004112 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4113 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4114 TOut.emitNop(IDLoc, STI);
4115 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4116 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4117 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4118 TOut.emitNop(IDLoc, STI);
4119 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4120 : Mips::CVT_W_S,
4121 FirstReg, SecondReg, IDLoc, STI);
4122 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4123 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004124 return false;
4125 }
4126
Daniel Sandersa736b372016-04-29 13:33:12 +00004127 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4128 : Mips::TRUNC_W_S,
4129 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004130
4131 return false;
4132}
4133
Daniel Sanders6394ee52015-10-15 14:52:58 +00004134bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004135 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004136 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004137 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004138 }
4139
Toma Tabacud88d79c2015-06-23 14:39:42 +00004140 const MCOperand &DstRegOp = Inst.getOperand(0);
4141 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004142 const MCOperand &SrcRegOp = Inst.getOperand(1);
4143 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004144 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4145 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4146
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004147 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004148 unsigned DstReg = DstRegOp.getReg();
4149 unsigned SrcReg = SrcRegOp.getReg();
4150 int64_t OffsetValue = OffsetImmOp.getImm();
4151
4152 // NOTE: We always need AT for ULHU, as it is always used as the source
4153 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004154 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004155 unsigned ATReg = getATReg(IDLoc);
4156 if (!ATReg)
4157 return true;
4158
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004159 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4160 if (IsLargeOffset) {
4161 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4162 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004163 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004164 }
4165
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004166 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4167 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4168 if (isLittle())
4169 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004170
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004171 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4172 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004173
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004174 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4175 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004176
Daniel Sandersa736b372016-04-29 13:33:12 +00004177 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004178 FirstOffset, IDLoc, STI);
4179 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004180 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004181 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004182
4183 return false;
4184}
4185
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004186bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004187 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004188 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004189 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004190 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004191
4192 const MCOperand &DstRegOp = Inst.getOperand(0);
4193 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004194 const MCOperand &SrcRegOp = Inst.getOperand(1);
4195 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004196 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4197 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4198
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004199 MipsTargetStreamer &TOut = getTargetStreamer();
4200 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004201 unsigned SrcReg = SrcRegOp.getReg();
4202 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004203
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004204 warnIfNoMacro(IDLoc);
4205 unsigned ATReg = getATReg(IDLoc);
4206 if (!ATReg)
4207 return true;
4208
4209 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4210 if (IsLargeOffset) {
4211 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4212 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004213 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004214 }
4215
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004216 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4217 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4218 if (isLittle())
4219 std::swap(FirstOffset, SecondOffset);
4220
4221 if (IsLargeOffset) {
4222 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4223 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4224 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4225 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4226 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4227 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004228 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004229 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4230 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4231 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004232 }
4233
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004234 return false;
4235}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004236
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004237bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4238 const MCSubtargetInfo *STI) {
4239 if (hasMips32r6() || hasMips64r6()) {
4240 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4241 }
4242
4243 const MCOperand &DstRegOp = Inst.getOperand(0);
4244 assert(DstRegOp.isReg() && "expected register operand kind");
4245 const MCOperand &SrcRegOp = Inst.getOperand(1);
4246 assert(SrcRegOp.isReg() && "expected register operand kind");
4247 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4248 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4249
4250 MipsTargetStreamer &TOut = getTargetStreamer();
4251 unsigned DstReg = DstRegOp.getReg();
4252 unsigned SrcReg = SrcRegOp.getReg();
4253 int64_t OffsetValue = OffsetImmOp.getImm();
4254
4255 // Compute left/right load/store offsets.
4256 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4257 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4258 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4259 if (isLittle())
4260 std::swap(LxlOffset, LxrOffset);
4261
4262 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4263 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4264 unsigned TmpReg = SrcReg;
4265 if (IsLargeOffset || DoMove) {
4266 warnIfNoMacro(IDLoc);
4267 TmpReg = getATReg(IDLoc);
4268 if (!TmpReg)
4269 return true;
4270 }
4271
4272 if (IsLargeOffset) {
4273 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4274 IDLoc, Out, STI))
4275 return true;
4276 }
4277
4278 if (DoMove)
4279 std::swap(DstReg, TmpReg);
4280
4281 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4282 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4283 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4284 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4285
4286 if (DoMove)
4287 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004288
4289 return false;
4290}
4291
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004292bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004293 MCStreamer &Out,
4294 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004295 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004296
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004297 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4298 assert(Inst.getOperand(0).isReg() &&
4299 Inst.getOperand(1).isReg() &&
4300 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004301
4302 unsigned ATReg = Mips::NoRegister;
4303 unsigned FinalDstReg = Mips::NoRegister;
4304 unsigned DstReg = Inst.getOperand(0).getReg();
4305 unsigned SrcReg = Inst.getOperand(1).getReg();
4306 int64_t ImmValue = Inst.getOperand(2).getImm();
4307
Simon Dardisaa208812017-02-24 14:34:32 +00004308 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004309
4310 unsigned FinalOpcode = Inst.getOpcode();
4311
4312 if (DstReg == SrcReg) {
4313 ATReg = getATReg(Inst.getLoc());
4314 if (!ATReg)
4315 return true;
4316 FinalDstReg = DstReg;
4317 DstReg = ATReg;
4318 }
4319
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004320 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004321 switch (FinalOpcode) {
4322 default:
4323 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004324 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004325 FinalOpcode = Mips::ADD;
4326 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004327 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004328 FinalOpcode = Mips::ADDu;
4329 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004330 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004331 FinalOpcode = Mips::AND;
4332 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004333 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004334 FinalOpcode = Mips::NOR;
4335 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004336 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004337 FinalOpcode = Mips::OR;
4338 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004339 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004340 FinalOpcode = Mips::SLT;
4341 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004342 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004343 FinalOpcode = Mips::SLTu;
4344 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004345 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004346 FinalOpcode = Mips::XOR;
4347 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004348 case Mips::ADDi_MM:
4349 FinalOpcode = Mips::ADD_MM;
4350 break;
4351 case Mips::ADDiu_MM:
4352 FinalOpcode = Mips::ADDu_MM;
4353 break;
4354 case Mips::ANDi_MM:
4355 FinalOpcode = Mips::AND_MM;
4356 break;
4357 case Mips::ORi_MM:
4358 FinalOpcode = Mips::OR_MM;
4359 break;
4360 case Mips::SLTi_MM:
4361 FinalOpcode = Mips::SLT_MM;
4362 break;
4363 case Mips::SLTiu_MM:
4364 FinalOpcode = Mips::SLTu_MM;
4365 break;
4366 case Mips::XORi_MM:
4367 FinalOpcode = Mips::XOR_MM;
4368 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004369 case Mips::ANDi64:
4370 FinalOpcode = Mips::AND64;
4371 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004372 case Mips::NORImm64:
4373 FinalOpcode = Mips::NOR64;
4374 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004375 case Mips::ORi64:
4376 FinalOpcode = Mips::OR64;
4377 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004378 case Mips::SLTImm64:
4379 FinalOpcode = Mips::SLT64;
4380 break;
4381 case Mips::SLTUImm64:
4382 FinalOpcode = Mips::SLTu64;
4383 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004384 case Mips::XORi64:
4385 FinalOpcode = Mips::XOR64;
4386 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004387 }
4388
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004389 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004390 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004391 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004392 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004393 return false;
4394 }
4395 return true;
4396}
4397
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004398bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4399 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004400 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004401 unsigned ATReg = Mips::NoRegister;
4402 unsigned DReg = Inst.getOperand(0).getReg();
4403 unsigned SReg = Inst.getOperand(1).getReg();
4404 unsigned TReg = Inst.getOperand(2).getReg();
4405 unsigned TmpReg = DReg;
4406
4407 unsigned FirstShift = Mips::NOP;
4408 unsigned SecondShift = Mips::NOP;
4409
4410 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004411 if (DReg == SReg) {
4412 TmpReg = getATReg(Inst.getLoc());
4413 if (!TmpReg)
4414 return true;
4415 }
4416
4417 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004418 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4419 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004420 return false;
4421 }
4422
4423 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004424 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004425 return false;
4426 }
4427
4428 return true;
4429 }
4430
4431 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004432 switch (Inst.getOpcode()) {
4433 default:
4434 llvm_unreachable("unexpected instruction opcode");
4435 case Mips::ROL:
4436 FirstShift = Mips::SRLV;
4437 SecondShift = Mips::SLLV;
4438 break;
4439 case Mips::ROR:
4440 FirstShift = Mips::SLLV;
4441 SecondShift = Mips::SRLV;
4442 break;
4443 }
4444
4445 ATReg = getATReg(Inst.getLoc());
4446 if (!ATReg)
4447 return true;
4448
Daniel Sandersa736b372016-04-29 13:33:12 +00004449 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4450 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4451 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4452 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004453
4454 return false;
4455 }
4456
4457 return true;
4458}
4459
4460bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004461 MCStreamer &Out,
4462 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004463 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004464 unsigned ATReg = Mips::NoRegister;
4465 unsigned DReg = Inst.getOperand(0).getReg();
4466 unsigned SReg = Inst.getOperand(1).getReg();
4467 int64_t ImmValue = Inst.getOperand(2).getImm();
4468
4469 unsigned FirstShift = Mips::NOP;
4470 unsigned SecondShift = Mips::NOP;
4471
4472 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004473 if (Inst.getOpcode() == Mips::ROLImm) {
4474 uint64_t MaxShift = 32;
4475 uint64_t ShiftValue = ImmValue;
4476 if (ImmValue != 0)
4477 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004478 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004479 return false;
4480 }
4481
4482 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004483 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004484 return false;
4485 }
4486
4487 return true;
4488 }
4489
4490 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004491 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004492 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004493 return false;
4494 }
4495
4496 switch (Inst.getOpcode()) {
4497 default:
4498 llvm_unreachable("unexpected instruction opcode");
4499 case Mips::ROLImm:
4500 FirstShift = Mips::SLL;
4501 SecondShift = Mips::SRL;
4502 break;
4503 case Mips::RORImm:
4504 FirstShift = Mips::SRL;
4505 SecondShift = Mips::SLL;
4506 break;
4507 }
4508
4509 ATReg = getATReg(Inst.getLoc());
4510 if (!ATReg)
4511 return true;
4512
Daniel Sandersa736b372016-04-29 13:33:12 +00004513 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4514 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4515 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004516
4517 return false;
4518 }
4519
4520 return true;
4521}
4522
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004523bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4524 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004525 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004526 unsigned ATReg = Mips::NoRegister;
4527 unsigned DReg = Inst.getOperand(0).getReg();
4528 unsigned SReg = Inst.getOperand(1).getReg();
4529 unsigned TReg = Inst.getOperand(2).getReg();
4530 unsigned TmpReg = DReg;
4531
4532 unsigned FirstShift = Mips::NOP;
4533 unsigned SecondShift = Mips::NOP;
4534
4535 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004536 if (TmpReg == SReg) {
4537 TmpReg = getATReg(Inst.getLoc());
4538 if (!TmpReg)
4539 return true;
4540 }
4541
4542 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004543 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4544 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004545 return false;
4546 }
4547
4548 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004549 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004550 return false;
4551 }
4552
4553 return true;
4554 }
4555
4556 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004557 switch (Inst.getOpcode()) {
4558 default:
4559 llvm_unreachable("unexpected instruction opcode");
4560 case Mips::DROL:
4561 FirstShift = Mips::DSRLV;
4562 SecondShift = Mips::DSLLV;
4563 break;
4564 case Mips::DROR:
4565 FirstShift = Mips::DSLLV;
4566 SecondShift = Mips::DSRLV;
4567 break;
4568 }
4569
4570 ATReg = getATReg(Inst.getLoc());
4571 if (!ATReg)
4572 return true;
4573
Daniel Sandersa736b372016-04-29 13:33:12 +00004574 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4575 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4576 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4577 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004578
4579 return false;
4580 }
4581
4582 return true;
4583}
4584
4585bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004586 MCStreamer &Out,
4587 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004588 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004589 unsigned ATReg = Mips::NoRegister;
4590 unsigned DReg = Inst.getOperand(0).getReg();
4591 unsigned SReg = Inst.getOperand(1).getReg();
4592 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4593
4594 unsigned FirstShift = Mips::NOP;
4595 unsigned SecondShift = Mips::NOP;
4596
4597 MCInst TmpInst;
4598
4599 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004600 unsigned FinalOpcode = Mips::NOP;
4601 if (ImmValue == 0)
4602 FinalOpcode = Mips::DROTR;
4603 else if (ImmValue % 32 == 0)
4604 FinalOpcode = Mips::DROTR32;
4605 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4606 if (Inst.getOpcode() == Mips::DROLImm)
4607 FinalOpcode = Mips::DROTR32;
4608 else
4609 FinalOpcode = Mips::DROTR;
4610 } else if (ImmValue >= 33) {
4611 if (Inst.getOpcode() == Mips::DROLImm)
4612 FinalOpcode = Mips::DROTR;
4613 else
4614 FinalOpcode = Mips::DROTR32;
4615 }
4616
4617 uint64_t ShiftValue = ImmValue % 32;
4618 if (Inst.getOpcode() == Mips::DROLImm)
4619 ShiftValue = (32 - ImmValue % 32) % 32;
4620
Daniel Sandersa736b372016-04-29 13:33:12 +00004621 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004622
4623 return false;
4624 }
4625
4626 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004627 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004628 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004629 return false;
4630 }
4631
4632 switch (Inst.getOpcode()) {
4633 default:
4634 llvm_unreachable("unexpected instruction opcode");
4635 case Mips::DROLImm:
4636 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4637 FirstShift = Mips::DSLL;
4638 SecondShift = Mips::DSRL32;
4639 }
4640 if (ImmValue == 32) {
4641 FirstShift = Mips::DSLL32;
4642 SecondShift = Mips::DSRL32;
4643 }
4644 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4645 FirstShift = Mips::DSLL32;
4646 SecondShift = Mips::DSRL;
4647 }
4648 break;
4649 case Mips::DRORImm:
4650 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4651 FirstShift = Mips::DSRL;
4652 SecondShift = Mips::DSLL32;
4653 }
4654 if (ImmValue == 32) {
4655 FirstShift = Mips::DSRL32;
4656 SecondShift = Mips::DSLL32;
4657 }
4658 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4659 FirstShift = Mips::DSRL32;
4660 SecondShift = Mips::DSLL;
4661 }
4662 break;
4663 }
4664
4665 ATReg = getATReg(Inst.getLoc());
4666 if (!ATReg)
4667 return true;
4668
Daniel Sandersa736b372016-04-29 13:33:12 +00004669 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4670 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4671 Inst.getLoc(), STI);
4672 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004673
4674 return false;
4675 }
4676
4677 return true;
4678}
4679
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004680bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4681 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004682 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004683 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4684 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4685
Daniel Sandersa736b372016-04-29 13:33:12 +00004686 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004687 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004688 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004689 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004690 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4691 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004692
4693 return false;
4694}
4695
Simon Dardis3c82a642017-02-08 16:25:05 +00004696bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4697 const MCSubtargetInfo *STI) {
4698 MipsTargetStreamer &TOut = getTargetStreamer();
4699 unsigned ATReg = Mips::NoRegister;
4700 unsigned DstReg = Inst.getOperand(0).getReg();
4701 unsigned SrcReg = Inst.getOperand(1).getReg();
4702 int32_t ImmValue = Inst.getOperand(2).getImm();
4703
4704 ATReg = getATReg(IDLoc);
4705 if (!ATReg)
4706 return true;
4707
4708 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4709
4710 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4711 SrcReg, ATReg, IDLoc, STI);
4712
4713 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4714
4715 return false;
4716}
4717
4718bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4719 const MCSubtargetInfo *STI) {
4720 MipsTargetStreamer &TOut = getTargetStreamer();
4721 unsigned ATReg = Mips::NoRegister;
4722 unsigned DstReg = Inst.getOperand(0).getReg();
4723 unsigned SrcReg = Inst.getOperand(1).getReg();
4724 unsigned TmpReg = Inst.getOperand(2).getReg();
4725
4726 ATReg = getATReg(Inst.getLoc());
4727 if (!ATReg)
4728 return true;
4729
4730 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4731 SrcReg, TmpReg, IDLoc, STI);
4732
4733 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4734
4735 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4736 DstReg, DstReg, 0x1F, IDLoc, STI);
4737
4738 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4739
4740 if (useTraps()) {
4741 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4742 } else {
4743 MCContext & Context = TOut.getStreamer().getContext();
4744 MCSymbol * BrTarget = Context.createTempSymbol();
4745 MCOperand LabelOp =
4746 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4747
4748 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4749 if (AssemblerOptions.back()->isReorder())
4750 TOut.emitNop(IDLoc, STI);
4751 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4752
4753 TOut.getStreamer().EmitLabel(BrTarget);
4754 }
4755 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4756
4757 return false;
4758}
4759
4760bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4761 const MCSubtargetInfo *STI) {
4762 MipsTargetStreamer &TOut = getTargetStreamer();
4763 unsigned ATReg = Mips::NoRegister;
4764 unsigned DstReg = Inst.getOperand(0).getReg();
4765 unsigned SrcReg = Inst.getOperand(1).getReg();
4766 unsigned TmpReg = Inst.getOperand(2).getReg();
4767
4768 ATReg = getATReg(IDLoc);
4769 if (!ATReg)
4770 return true;
4771
4772 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4773 SrcReg, TmpReg, IDLoc, STI);
4774
4775 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4776 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4777 if (useTraps()) {
4778 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4779 } else {
4780 MCContext & Context = TOut.getStreamer().getContext();
4781 MCSymbol * BrTarget = Context.createTempSymbol();
4782 MCOperand LabelOp =
4783 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4784
4785 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4786 if (AssemblerOptions.back()->isReorder())
4787 TOut.emitNop(IDLoc, STI);
4788 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4789
4790 TOut.getStreamer().EmitLabel(BrTarget);
4791 }
4792
4793 return false;
4794}
4795
4796bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4797 const MCSubtargetInfo *STI) {
4798 MipsTargetStreamer &TOut = getTargetStreamer();
4799 unsigned DstReg = Inst.getOperand(0).getReg();
4800 unsigned SrcReg = Inst.getOperand(1).getReg();
4801 unsigned TmpReg = Inst.getOperand(2).getReg();
4802
4803 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4804 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4805
4806 return false;
4807}
4808
Simon Dardisaff4d142016-10-18 14:28:00 +00004809// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4810// lw $<reg+1>>, offset+4($reg2)'
4811// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4812// sw $<reg+1>>, offset+4($reg2)'
4813// for O32.
4814bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4815 MCStreamer &Out,
4816 const MCSubtargetInfo *STI,
4817 bool IsLoad) {
4818 if (!isABI_O32())
4819 return true;
4820
4821 warnIfNoMacro(IDLoc);
4822
4823 MipsTargetStreamer &TOut = getTargetStreamer();
4824 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4825 unsigned FirstReg = Inst.getOperand(0).getReg();
4826 unsigned SecondReg = nextReg(FirstReg);
4827 unsigned BaseReg = Inst.getOperand(1).getReg();
4828 if (!SecondReg)
4829 return true;
4830
4831 warnIfRegIndexIsAT(FirstReg, IDLoc);
4832
4833 assert(Inst.getOperand(2).isImm() &&
4834 "Offset for load macro is not immediate!");
4835
4836 MCOperand &FirstOffset = Inst.getOperand(2);
4837 signed NextOffset = FirstOffset.getImm() + 4;
4838 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4839
4840 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4841 return true;
4842
4843 // For loads, clobber the base register with the second load instead of the
4844 // first if the BaseReg == FirstReg.
4845 if (FirstReg != BaseReg || !IsLoad) {
4846 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4847 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4848 } else {
4849 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4850 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4851 }
4852
4853 return false;
4854}
4855
Simon Dardis43115a12016-11-21 20:30:41 +00004856bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4857 const MCSubtargetInfo *STI) {
4858
4859 warnIfNoMacro(IDLoc);
4860 MipsTargetStreamer &TOut = getTargetStreamer();
4861
4862 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4863 Inst.getOperand(2).getReg() != Mips::ZERO) {
4864 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4865 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4866 IDLoc, STI);
4867 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4868 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4869 return false;
4870 }
4871
4872 unsigned Reg = 0;
4873 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4874 Reg = Inst.getOperand(2).getReg();
4875 } else {
4876 Reg = Inst.getOperand(1).getReg();
4877 }
4878 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4879 return false;
4880}
4881
4882bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4883 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004884 warnIfNoMacro(IDLoc);
4885 MipsTargetStreamer &TOut = getTargetStreamer();
4886
4887 unsigned Opc;
4888 int64_t Imm = Inst.getOperand(2).getImm();
4889 unsigned Reg = Inst.getOperand(1).getReg();
4890
4891 if (Imm == 0) {
4892 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4893 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4894 return false;
4895 } else {
4896
4897 if (Reg == Mips::ZERO) {
4898 Warning(IDLoc, "comparison is always false");
4899 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4900 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4901 return false;
4902 }
4903
4904 if (Imm > -0x8000 && Imm < 0) {
4905 Imm = -Imm;
4906 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4907 } else {
4908 Opc = Mips::XORi;
4909 }
4910 }
4911 if (!isUInt<16>(Imm)) {
4912 unsigned ATReg = getATReg(IDLoc);
4913 if (!ATReg)
4914 return true;
4915
4916 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4917 Out, STI))
4918 return true;
4919
4920 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4921 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4922 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4923 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4924 return false;
4925 }
4926
4927 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4928 Imm, IDLoc, STI);
4929 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4930 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4931 return false;
4932}
4933
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004934// Map the DSP accumulator and control register to the corresponding gpr
4935// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4936// do not map the DSP registers contigously to gpr registers.
4937static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4938 switch (Inst.getOpcode()) {
4939 case Mips::MFTLO:
4940 case Mips::MTTLO:
4941 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4942 case Mips::AC0:
4943 return Mips::ZERO;
4944 case Mips::AC1:
4945 return Mips::A0;
4946 case Mips::AC2:
4947 return Mips::T0;
4948 case Mips::AC3:
4949 return Mips::T4;
4950 default:
4951 llvm_unreachable("Unknown register for 'mttr' alias!");
4952 }
4953 case Mips::MFTHI:
4954 case Mips::MTTHI:
4955 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4956 case Mips::AC0:
4957 return Mips::AT;
4958 case Mips::AC1:
4959 return Mips::A1;
4960 case Mips::AC2:
4961 return Mips::T1;
4962 case Mips::AC3:
4963 return Mips::T5;
4964 default:
4965 llvm_unreachable("Unknown register for 'mttr' alias!");
4966 }
4967 case Mips::MFTACX:
4968 case Mips::MTTACX:
4969 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4970 case Mips::AC0:
4971 return Mips::V0;
4972 case Mips::AC1:
4973 return Mips::A2;
4974 case Mips::AC2:
4975 return Mips::T2;
4976 case Mips::AC3:
4977 return Mips::T6;
4978 default:
4979 llvm_unreachable("Unknown register for 'mttr' alias!");
4980 }
4981 case Mips::MFTDSP:
4982 case Mips::MTTDSP:
4983 return Mips::S0;
4984 default:
4985 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4986 }
4987}
4988
4989// Map the floating point register operand to the corresponding register
4990// operand.
4991static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4992 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4993 case Mips::F0: return Mips::ZERO;
4994 case Mips::F1: return Mips::AT;
4995 case Mips::F2: return Mips::V0;
4996 case Mips::F3: return Mips::V1;
4997 case Mips::F4: return Mips::A0;
4998 case Mips::F5: return Mips::A1;
4999 case Mips::F6: return Mips::A2;
5000 case Mips::F7: return Mips::A3;
5001 case Mips::F8: return Mips::T0;
5002 case Mips::F9: return Mips::T1;
5003 case Mips::F10: return Mips::T2;
5004 case Mips::F11: return Mips::T3;
5005 case Mips::F12: return Mips::T4;
5006 case Mips::F13: return Mips::T5;
5007 case Mips::F14: return Mips::T6;
5008 case Mips::F15: return Mips::T7;
5009 case Mips::F16: return Mips::S0;
5010 case Mips::F17: return Mips::S1;
5011 case Mips::F18: return Mips::S2;
5012 case Mips::F19: return Mips::S3;
5013 case Mips::F20: return Mips::S4;
5014 case Mips::F21: return Mips::S5;
5015 case Mips::F22: return Mips::S6;
5016 case Mips::F23: return Mips::S7;
5017 case Mips::F24: return Mips::T8;
5018 case Mips::F25: return Mips::T9;
5019 case Mips::F26: return Mips::K0;
5020 case Mips::F27: return Mips::K1;
5021 case Mips::F28: return Mips::GP;
5022 case Mips::F29: return Mips::SP;
5023 case Mips::F30: return Mips::FP;
5024 case Mips::F31: return Mips::RA;
5025 default: llvm_unreachable("Unknown register for mttc1 alias!");
5026 }
5027}
5028
5029// Map the coprocessor operand the corresponding gpr register operand.
5030static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5031 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5032 case Mips::COP00: return Mips::ZERO;
5033 case Mips::COP01: return Mips::AT;
5034 case Mips::COP02: return Mips::V0;
5035 case Mips::COP03: return Mips::V1;
5036 case Mips::COP04: return Mips::A0;
5037 case Mips::COP05: return Mips::A1;
5038 case Mips::COP06: return Mips::A2;
5039 case Mips::COP07: return Mips::A3;
5040 case Mips::COP08: return Mips::T0;
5041 case Mips::COP09: return Mips::T1;
5042 case Mips::COP010: return Mips::T2;
5043 case Mips::COP011: return Mips::T3;
5044 case Mips::COP012: return Mips::T4;
5045 case Mips::COP013: return Mips::T5;
5046 case Mips::COP014: return Mips::T6;
5047 case Mips::COP015: return Mips::T7;
5048 case Mips::COP016: return Mips::S0;
5049 case Mips::COP017: return Mips::S1;
5050 case Mips::COP018: return Mips::S2;
5051 case Mips::COP019: return Mips::S3;
5052 case Mips::COP020: return Mips::S4;
5053 case Mips::COP021: return Mips::S5;
5054 case Mips::COP022: return Mips::S6;
5055 case Mips::COP023: return Mips::S7;
5056 case Mips::COP024: return Mips::T8;
5057 case Mips::COP025: return Mips::T9;
5058 case Mips::COP026: return Mips::K0;
5059 case Mips::COP027: return Mips::K1;
5060 case Mips::COP028: return Mips::GP;
5061 case Mips::COP029: return Mips::SP;
5062 case Mips::COP030: return Mips::FP;
5063 case Mips::COP031: return Mips::RA;
5064 default: llvm_unreachable("Unknown register for mttc0 alias!");
5065 }
5066}
5067
5068/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5069/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5070bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5071 const MCSubtargetInfo *STI) {
5072 MipsTargetStreamer &TOut = getTargetStreamer();
5073 unsigned rd = 0;
5074 unsigned u = 1;
5075 unsigned sel = 0;
5076 unsigned h = 0;
5077 bool IsMFTR = false;
5078 switch (Inst.getOpcode()) {
5079 case Mips::MFTC0:
5080 IsMFTR = true;
5081 LLVM_FALLTHROUGH;
5082 case Mips::MTTC0:
5083 u = 0;
5084 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5085 sel = Inst.getOperand(2).getImm();
5086 break;
5087 case Mips::MFTGPR:
5088 IsMFTR = true;
5089 LLVM_FALLTHROUGH;
5090 case Mips::MTTGPR:
5091 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5092 break;
5093 case Mips::MFTLO:
5094 case Mips::MFTHI:
5095 case Mips::MFTACX:
5096 case Mips::MFTDSP:
5097 IsMFTR = true;
5098 LLVM_FALLTHROUGH;
5099 case Mips::MTTLO:
5100 case Mips::MTTHI:
5101 case Mips::MTTACX:
5102 case Mips::MTTDSP:
5103 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5104 sel = 1;
5105 break;
5106 case Mips::MFTHC1:
5107 h = 1;
5108 LLVM_FALLTHROUGH;
5109 case Mips::MFTC1:
5110 IsMFTR = true;
5111 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5112 sel = 2;
5113 break;
5114 case Mips::MTTHC1:
5115 h = 1;
5116 LLVM_FALLTHROUGH;
5117 case Mips::MTTC1:
5118 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5119 sel = 2;
5120 break;
5121 case Mips::CFTC1:
5122 IsMFTR = true;
5123 LLVM_FALLTHROUGH;
5124 case Mips::CTTC1:
5125 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5126 sel = 3;
5127 break;
5128 }
5129 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5130 unsigned Op1 =
5131 IsMFTR ? rd
5132 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5133 : Inst.getOperand(0).getReg());
5134
5135 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5136 STI);
5137 return false;
5138}
5139
Daniel Sandersc5537422016-07-27 13:49:44 +00005140unsigned
5141MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5142 const OperandVector &Operands) {
5143 switch (Inst.getOpcode()) {
5144 default:
5145 return Match_Success;
5146 case Mips::DATI:
5147 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005148 if (static_cast<MipsOperand &>(*Operands[1])
5149 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5150 return Match_Success;
5151 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005152 }
5153}
Simon Dardis730fdb72017-01-16 13:55:58 +00005154
Matheus Almeida595fcab2014-06-11 15:05:56 +00005155unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005156 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005157 // As described by the MIPSR6 spec, daui must not use the zero operand for
5158 // its source operand.
5159 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005160 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5161 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5162 return Match_RequiresNoZeroRegister;
5163 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005164 // As described by the Mips32r2 spec, the registers Rd and Rs for
5165 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005166 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005167 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005168 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005169 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005170 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005171 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005172 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5173 return Match_RequiresDifferentSrcAndDst;
5174 return Match_Success;
5175 case Mips::LWP_MM:
5176 case Mips::LWP_MMR6:
5177 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5178 return Match_RequiresDifferentSrcAndDst;
5179 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005180 case Mips::SYNC:
5181 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5182 return Match_NonZeroOperandForSync;
5183 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005184 case Mips::MFC0:
5185 case Mips::MTC0:
5186 case Mips::MTC2:
5187 case Mips::MFC2:
5188 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5189 return Match_NonZeroOperandForMTCX;
5190 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005191 // As described the MIPSR6 spec, the compact branches that compare registers
5192 // must:
5193 // a) Not use the zero register.
5194 // b) Not use the same register twice.
5195 // c) rs < rt for bnec, beqc.
5196 // NB: For this case, the encoding will swap the operands as their
5197 // ordering doesn't matter. GAS performs this transformation too.
5198 // Hence, that constraint does not have to be enforced.
5199 //
5200 // The compact branches that branch iff the signed addition of two registers
5201 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5202 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005203 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5204 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5205 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5206 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5207 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5208 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005209 case Mips::BLEZC64:
5210 case Mips::BGEZC64:
5211 case Mips::BGTZC64:
5212 case Mips::BLTZC64:
5213 case Mips::BEQZC64:
5214 case Mips::BNEZC64:
5215 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5216 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005217 return Match_RequiresNoZeroRegister;
5218 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005219 case Mips::BGEC: case Mips::BGEC_MMR6:
5220 case Mips::BLTC: case Mips::BLTC_MMR6:
5221 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5222 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5223 case Mips::BEQC: case Mips::BEQC_MMR6:
5224 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005225 case Mips::BGEC64:
5226 case Mips::BLTC64:
5227 case Mips::BGEUC64:
5228 case Mips::BLTUC64:
5229 case Mips::BEQC64:
5230 case Mips::BNEC64:
5231 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5232 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005233 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005234 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5235 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005236 return Match_RequiresNoZeroRegister;
5237 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5238 return Match_RequiresDifferentOperands;
5239 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005240 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005241 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5242 "Operands must be immediates for dins!");
5243 const signed Pos = Inst.getOperand(2).getImm();
5244 const signed Size = Inst.getOperand(3).getImm();
5245 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5246 return Match_RequiresPosSizeRange0_32;
5247 return Match_Success;
5248 }
5249 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005250 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005251 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5252 "Operands must be immediates for dinsm/dinsu!");
5253 const signed Pos = Inst.getOperand(2).getImm();
5254 const signed Size = Inst.getOperand(3).getImm();
5255 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5256 return Match_RequiresPosSizeRange33_64;
5257 return Match_Success;
5258 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005259 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005260 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5261 "Operands must be immediates for DEXTM!");
5262 const signed Pos = Inst.getOperand(2).getImm();
5263 const signed Size = Inst.getOperand(3).getImm();
5264 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5265 return Match_RequiresPosSizeUImm6;
5266 return Match_Success;
5267 }
5268 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005269 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005270 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5271 "Operands must be immediates for dextm/dextu!");
5272 const signed Pos = Inst.getOperand(2).getImm();
5273 const signed Size = Inst.getOperand(3).getImm();
5274 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5275 return Match_RequiresPosSizeRange33_64;
5276 return Match_Success;
5277 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005278 case Mips::CRC32B: case Mips::CRC32CB:
5279 case Mips::CRC32H: case Mips::CRC32CH:
5280 case Mips::CRC32W: case Mips::CRC32CW:
5281 case Mips::CRC32D: case Mips::CRC32CD:
5282 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5283 return Match_RequiresSameSrcAndDst;
5284 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005285 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005286
5287 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5288 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5289 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5290 return Match_NoFCCRegisterForCurrentISA;
5291
5292 return Match_Success;
5293
Matheus Almeida595fcab2014-06-11 15:05:56 +00005294}
5295
Daniel Sanders52da7af2015-11-06 12:11:03 +00005296static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5297 uint64_t ErrorInfo) {
5298 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5299 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5300 if (ErrorLoc == SMLoc())
5301 return Loc;
5302 return ErrorLoc;
5303 }
5304 return Loc;
5305}
5306
David Blaikie960ea3f2014-06-08 16:18:35 +00005307bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5308 OperandVector &Operands,
5309 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005310 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005311 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005312 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005313 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005314 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005315
5316 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005317 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005318 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005319 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005320 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005321 case Match_MissingFeature:
5322 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5323 return true;
5324 case Match_InvalidOperand: {
5325 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005326 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005327 if (ErrorInfo >= Operands.size())
5328 return Error(IDLoc, "too few operands for instruction");
5329
Daniel Sanders52da7af2015-11-06 12:11:03 +00005330 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005331 if (ErrorLoc == SMLoc())
5332 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005333 }
5334
5335 return Error(ErrorLoc, "invalid operand for instruction");
5336 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005337 case Match_NonZeroOperandForSync:
5338 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005339 case Match_NonZeroOperandForMTCX:
5340 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005341 case Match_MnemonicFail:
5342 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005343 case Match_RequiresDifferentSrcAndDst:
5344 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005345 case Match_RequiresDifferentOperands:
5346 return Error(IDLoc, "registers must be different");
5347 case Match_RequiresNoZeroRegister:
5348 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005349 case Match_RequiresSameSrcAndDst:
5350 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005351 case Match_NoFCCRegisterForCurrentISA:
5352 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5353 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005354 case Match_Immz:
5355 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005356 case Match_UImm1_0:
5357 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5358 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005359 case Match_UImm2_0:
5360 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5361 "expected 2-bit unsigned immediate");
5362 case Match_UImm2_1:
5363 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5364 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005365 case Match_UImm3_0:
5366 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5367 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005368 case Match_UImm4_0:
5369 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5370 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005371 case Match_SImm4_0:
5372 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5373 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005374 case Match_UImm5_0:
5375 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5376 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005377 case Match_SImm5_0:
5378 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5379 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005380 case Match_UImm5_1:
5381 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5382 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005383 case Match_UImm5_32:
5384 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5385 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005386 case Match_UImm5_33:
5387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5388 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005389 case Match_UImm5_0_Report_UImm6:
5390 // This is used on UImm5 operands that have a corresponding UImm5_32
5391 // operand to avoid confusing the user.
5392 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5393 "expected 6-bit unsigned immediate");
5394 case Match_UImm5_Lsl2:
5395 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5396 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005397 case Match_UImmRange2_64:
5398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5399 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005400 case Match_UImm6_0:
5401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5402 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005403 case Match_UImm6_Lsl2:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005406 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5408 "expected 6-bit signed immediate");
5409 case Match_UImm7_0:
5410 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5411 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005412 case Match_UImm7_N1:
5413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5414 "expected immediate in range -1 .. 126");
5415 case Match_SImm7_Lsl2:
5416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5417 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005418 case Match_UImm8_0:
5419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5420 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005421 case Match_UImm10_0:
5422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5423 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005424 case Match_SImm10_0:
5425 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5426 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005427 case Match_SImm11_0:
5428 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5429 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005430 case Match_UImm16:
5431 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005432 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005433 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5434 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005435 case Match_SImm16:
5436 case Match_SImm16_Relaxed:
5437 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5438 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005439 case Match_SImm19_Lsl2:
5440 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5441 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005442 case Match_UImm20_0:
5443 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5444 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005445 case Match_UImm26_0:
5446 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5447 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005448 case Match_SImm32:
5449 case Match_SImm32_Relaxed:
5450 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5451 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005452 case Match_UImm32_Coerced:
5453 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5454 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005455 case Match_MemSImm9:
5456 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5457 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005458 case Match_MemSImm10:
5459 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5460 "expected memory with 10-bit signed offset");
5461 case Match_MemSImm10Lsl1:
5462 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5463 "expected memory with 11-bit signed offset and multiple of 2");
5464 case Match_MemSImm10Lsl2:
5465 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5466 "expected memory with 12-bit signed offset and multiple of 4");
5467 case Match_MemSImm10Lsl3:
5468 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5469 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005470 case Match_MemSImm11:
5471 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5472 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005473 case Match_MemSImm12:
5474 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5475 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005476 case Match_MemSImm16:
5477 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5478 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005479 case Match_MemSImmPtr:
5480 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5481 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005482 case Match_RequiresPosSizeRange0_32: {
5483 SMLoc ErrorStart = Operands[3]->getStartLoc();
5484 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5485 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5486 SMRange(ErrorStart, ErrorEnd));
5487 }
Simon Dardis55e44672017-09-14 17:27:53 +00005488 case Match_RequiresPosSizeUImm6: {
5489 SMLoc ErrorStart = Operands[3]->getStartLoc();
5490 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5491 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5492 SMRange(ErrorStart, ErrorEnd));
5493 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005494 case Match_RequiresPosSizeRange33_64: {
5495 SMLoc ErrorStart = Operands[3]->getStartLoc();
5496 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5497 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5498 SMRange(ErrorStart, ErrorEnd));
5499 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005500 }
Craig Topper589ceee2015-01-03 08:16:34 +00005501
5502 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005503}
5504
Toma Tabacud9d344b2015-04-27 14:05:04 +00005505void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5506 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5507 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5508 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005509}
5510
Toma Tabacu81496c12015-05-20 08:54:45 +00005511void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5512 if (!AssemblerOptions.back()->isMacro())
5513 Warning(Loc, "macro instruction expanded into multiple instructions");
5514}
5515
Daniel Sandersef638fe2014-10-03 15:37:37 +00005516void
5517MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5518 SMRange Range, bool ShowColors) {
5519 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005520 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005521 ShowColors);
5522}
5523
Jack Carter1ac53222013-02-20 23:11:17 +00005524int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005525 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005526
Vladimir Medic4c299852013-11-06 11:27:05 +00005527 CC = StringSwitch<unsigned>(Name)
5528 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005529 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005530 .Case("a0", 4)
5531 .Case("a1", 5)
5532 .Case("a2", 6)
5533 .Case("a3", 7)
5534 .Case("v0", 2)
5535 .Case("v1", 3)
5536 .Case("s0", 16)
5537 .Case("s1", 17)
5538 .Case("s2", 18)
5539 .Case("s3", 19)
5540 .Case("s4", 20)
5541 .Case("s5", 21)
5542 .Case("s6", 22)
5543 .Case("s7", 23)
5544 .Case("k0", 26)
5545 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005546 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005547 .Case("sp", 29)
5548 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005549 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005550 .Case("ra", 31)
5551 .Case("t0", 8)
5552 .Case("t1", 9)
5553 .Case("t2", 10)
5554 .Case("t3", 11)
5555 .Case("t4", 12)
5556 .Case("t5", 13)
5557 .Case("t6", 14)
5558 .Case("t7", 15)
5559 .Case("t8", 24)
5560 .Case("t9", 25)
5561 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005562
Toma Tabacufda445c2014-09-15 15:33:01 +00005563 if (!(isABI_N32() || isABI_N64()))
5564 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005565
Daniel Sandersef638fe2014-10-03 15:37:37 +00005566 if (12 <= CC && CC <= 15) {
5567 // Name is one of t4-t7
5568 AsmToken RegTok = getLexer().peekTok();
5569 SMRange RegRange = RegTok.getLocRange();
5570
5571 StringRef FixedName = StringSwitch<StringRef>(Name)
5572 .Case("t4", "t0")
5573 .Case("t5", "t1")
5574 .Case("t6", "t2")
5575 .Case("t7", "t3")
5576 .Default("");
5577 assert(FixedName != "" && "Register name is not one of t4-t7.");
5578
5579 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5580 "Did you mean $" + FixedName + "?", RegRange);
5581 }
5582
Toma Tabacufda445c2014-09-15 15:33:01 +00005583 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5584 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5585 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5586 if (8 <= CC && CC <= 11)
5587 CC += 4;
5588
5589 if (CC == -1)
5590 CC = StringSwitch<unsigned>(Name)
5591 .Case("a4", 8)
5592 .Case("a5", 9)
5593 .Case("a6", 10)
5594 .Case("a7", 11)
5595 .Case("kt0", 26)
5596 .Case("kt1", 27)
5597 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005598
5599 return CC;
5600}
Jack Carterd0bd6422013-04-18 00:41:53 +00005601
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005602int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5603 int CC;
5604
5605 CC = StringSwitch<unsigned>(Name)
5606 .Case("hwr_cpunum", 0)
5607 .Case("hwr_synci_step", 1)
5608 .Case("hwr_cc", 2)
5609 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005610 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005611 .Default(-1);
5612
5613 return CC;
5614}
5615
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005616int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005617 if (Name[0] == 'f') {
5618 StringRef NumString = Name.substr(1);
5619 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005620 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005621 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005622 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005623 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005624 return IntVal;
5625 }
5626 return -1;
5627}
Jack Cartera63b16a2012-09-07 00:23:42 +00005628
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005629int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005630 if (Name.startswith("fcc")) {
5631 StringRef NumString = Name.substr(3);
5632 unsigned IntVal;
5633 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005634 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005635 if (IntVal > 7) // There are only 8 fcc registers.
5636 return -1;
5637 return IntVal;
5638 }
5639 return -1;
5640}
5641
5642int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005643 if (Name.startswith("ac")) {
5644 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005645 unsigned IntVal;
5646 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005647 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005648 if (IntVal > 3) // There are only 3 acc registers.
5649 return -1;
5650 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005651 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005652 return -1;
5653}
Jack Carterd0bd6422013-04-18 00:41:53 +00005654
Jack Carter5dc8ac92013-09-25 23:50:44 +00005655int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5656 unsigned IntVal;
5657
5658 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5659 return -1;
5660
5661 if (IntVal > 31)
5662 return -1;
5663
5664 return IntVal;
5665}
5666
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005667int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5668 int CC;
5669
5670 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005671 .Case("msair", 0)
5672 .Case("msacsr", 1)
5673 .Case("msaaccess", 2)
5674 .Case("msasave", 3)
5675 .Case("msamodify", 4)
5676 .Case("msarequest", 5)
5677 .Case("msamap", 6)
5678 .Case("msaunmap", 7)
5679 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005680
5681 return CC;
5682}
5683
Simon Dardis3aa8a902017-02-06 12:43:46 +00005684bool MipsAsmParser::canUseATReg() {
5685 return AssemblerOptions.back()->getATRegIndex() != 0;
5686}
5687
Toma Tabacu89a712b2015-04-15 10:48:56 +00005688unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005689 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005690 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005691 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005692 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005693 return 0;
5694 }
5695 unsigned AT = getReg(
5696 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005697 return AT;
5698}
Jack Carter0b744b32012-10-04 02:29:46 +00005699
Jack Carterd0bd6422013-04-18 00:41:53 +00005700unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005701 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005702}
5703
Toma Tabacu13964452014-09-04 13:23:44 +00005704bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005705 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005706 LLVM_DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005707
Jack Carter30a59822012-10-04 04:03:53 +00005708 // Check if the current operand has a custom associated parser, if so, try to
5709 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005710 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5711 if (ResTy == MatchOperand_Success)
5712 return false;
5713 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5714 // there was a match, but an error occurred, in which case, just return that
5715 // the operand parsing failed.
5716 if (ResTy == MatchOperand_ParseFail)
5717 return true;
5718
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005719 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005720
Jack Carterb4dbc172012-09-05 23:34:03 +00005721 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005722 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005723 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005724 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005725
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005726 // Almost all registers have been parsed by custom parsers. There is only
5727 // one exception to this. $zero (and it's alias $0) will reach this point
5728 // for div, divu, and similar instructions because it is not an operand
5729 // to the instruction definition but an explicit register. Special case
5730 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005731 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005732 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005733
Jack Carterd0bd6422013-04-18 00:41:53 +00005734 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005735 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005736 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005737 return true;
5738
Jack Carter873c7242013-01-12 01:03:14 +00005739 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005740 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005741 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005742 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005743 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005744
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005745 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005746 return false;
5747 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005748 default: {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005749 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005750
5751 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005752 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005753 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005754 return true;
5755
Jack Carter873c7242013-01-12 01:03:14 +00005756 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5757
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005758 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005759 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005760 }
Jack Carter0b744b32012-10-04 02:29:46 +00005761 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005762 return true;
5763}
5764
Jack Carterb5cf5902013-04-17 00:18:04 +00005765bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005766 switch (Expr->getKind()) {
5767 case MCExpr::Constant:
5768 return true;
5769 case MCExpr::SymbolRef:
5770 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005771 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005772 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005773 if (!isEvaluated(BE->getLHS()))
5774 return false;
5775 return isEvaluated(BE->getRHS());
5776 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005777 case MCExpr::Unary:
5778 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005779 case MCExpr::Target:
5780 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005781 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005782 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005783}
Jack Carterd0bd6422013-04-18 00:41:53 +00005784
Jack Carterb4dbc172012-09-05 23:34:03 +00005785bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5786 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005787 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005788 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005789 if (ResTy == MatchOperand_Success) {
5790 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005791 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005792 StartLoc = Operand.getStartLoc();
5793 EndLoc = Operand.getEndLoc();
5794
5795 // AFAIK, we only support numeric registers and named GPR's in CFI
5796 // directives.
5797 // Don't worry about eating tokens before failing. Using an unrecognised
5798 // register is a parse error.
5799 if (Operand.isGPRAsmReg()) {
5800 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005801 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005802 }
5803
5804 return (RegNo == (unsigned)-1);
5805 }
5806
5807 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005808 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005809}
5810
Jack Carterb5cf5902013-04-17 00:18:04 +00005811bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005812 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005813
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005814 if (isParenExpr)
5815 return getParser().parseParenExprOfDepth(0, Res, S);
5816 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005817}
5818
Alex Bradbury58eba092016-11-01 16:32:05 +00005819OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005820MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005821 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005822 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005823 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005824 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005825 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005826 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005827 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005828 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005829
Jack Carterb5cf5902013-04-17 00:18:04 +00005830 if (getLexer().getKind() == AsmToken::LParen) {
5831 Parser.Lex();
5832 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005833 }
5834
Jack Carterb5cf5902013-04-17 00:18:04 +00005835 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005836 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005837 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005838
Jack Carterd0bd6422013-04-18 00:41:53 +00005839 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005840 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005841 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005842 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005843 SMLoc E =
5844 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005845 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005846 return MatchOperand_Success;
5847 }
5848 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005849 SMLoc E =
5850 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005851
Jack Carterd0bd6422013-04-18 00:41:53 +00005852 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005853 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005854 auto Base = MipsOperand::createGPRReg(
5855 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005856 Operands.push_back(
5857 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005858 return MatchOperand_Success;
5859 }
Simon Dardis858915f2016-10-18 15:17:17 +00005860 MCBinaryExpr::Opcode Opcode;
5861 // GAS and LLVM treat comparison operators different. GAS will generate -1
5862 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5863 // highly unlikely to be found in a memory offset expression, we don't
5864 // handle them.
5865 switch (Tok.getKind()) {
5866 case AsmToken::Plus:
5867 Opcode = MCBinaryExpr::Add;
5868 Parser.Lex();
5869 break;
5870 case AsmToken::Minus:
5871 Opcode = MCBinaryExpr::Sub;
5872 Parser.Lex();
5873 break;
5874 case AsmToken::Star:
5875 Opcode = MCBinaryExpr::Mul;
5876 Parser.Lex();
5877 break;
5878 case AsmToken::Pipe:
5879 Opcode = MCBinaryExpr::Or;
5880 Parser.Lex();
5881 break;
5882 case AsmToken::Amp:
5883 Opcode = MCBinaryExpr::And;
5884 Parser.Lex();
5885 break;
5886 case AsmToken::LessLess:
5887 Opcode = MCBinaryExpr::Shl;
5888 Parser.Lex();
5889 break;
5890 case AsmToken::GreaterGreater:
5891 Opcode = MCBinaryExpr::LShr;
5892 Parser.Lex();
5893 break;
5894 case AsmToken::Caret:
5895 Opcode = MCBinaryExpr::Xor;
5896 Parser.Lex();
5897 break;
5898 case AsmToken::Slash:
5899 Opcode = MCBinaryExpr::Div;
5900 Parser.Lex();
5901 break;
5902 case AsmToken::Percent:
5903 Opcode = MCBinaryExpr::Mod;
5904 Parser.Lex();
5905 break;
5906 default:
5907 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5908 return MatchOperand_ParseFail;
5909 }
5910 const MCExpr * NextExpr;
5911 if (getParser().parseExpression(NextExpr))
5912 return MatchOperand_ParseFail;
5913 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005914 }
5915
Jack Carterd0bd6422013-04-18 00:41:53 +00005916 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005917 }
5918
Toma Tabacu13964452014-09-04 13:23:44 +00005919 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005920 if (Res != MatchOperand_Success)
5921 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005922
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005923 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005924 Error(Parser.getTok().getLoc(), "')' expected");
5925 return MatchOperand_ParseFail;
5926 }
5927
Jack Carter873c7242013-01-12 01:03:14 +00005928 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5929
Jack Carterd0bd6422013-04-18 00:41:53 +00005930 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005931
Craig Topper062a2ba2014-04-25 05:30:21 +00005932 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005933 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005934
Jack Carterd0bd6422013-04-18 00:41:53 +00005935 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005936 std::unique_ptr<MipsOperand> op(
5937 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005938 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005939 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005940 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005941 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005942 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5943 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005944 if (IdVal->evaluateAsAbsolute(Imm))
5945 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005946 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005947 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005948 getContext());
5949 }
5950
David Blaikie960ea3f2014-06-08 16:18:35 +00005951 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005952 return MatchOperand_Success;
5953}
5954
David Blaikie960ea3f2014-06-08 16:18:35 +00005955bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005956 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005957 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005958 if (Sym) {
5959 SMLoc S = Parser.getTok().getLoc();
5960 const MCExpr *Expr;
5961 if (Sym->isVariable())
5962 Expr = Sym->getVariableValue();
5963 else
5964 return false;
5965 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005966 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005967 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005968 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005969 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005970 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005971 if (ResTy == MatchOperand_Success) {
5972 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005973 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005974 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005975 llvm_unreachable("Should never ParseFail");
5976 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005977 }
Jack Carterd76b2372013-03-21 21:44:16 +00005978 }
5979 }
5980 return false;
5981}
Jack Carterd0bd6422013-04-18 00:41:53 +00005982
Alex Bradbury58eba092016-11-01 16:32:05 +00005983OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005984MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005985 StringRef Identifier,
5986 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005987 int Index = matchCPURegisterName(Identifier);
5988 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005989 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005990 Index, Identifier, getContext().getRegisterInfo(), S,
5991 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005992 return MatchOperand_Success;
5993 }
5994
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005995 Index = matchHWRegsRegisterName(Identifier);
5996 if (Index != -1) {
5997 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005998 Index, Identifier, getContext().getRegisterInfo(), S,
5999 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006000 return MatchOperand_Success;
6001 }
6002
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006003 Index = matchFPURegisterName(Identifier);
6004 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006005 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006006 Index, Identifier, getContext().getRegisterInfo(), S,
6007 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006008 return MatchOperand_Success;
6009 }
6010
6011 Index = matchFCCRegisterName(Identifier);
6012 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006013 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006014 Index, Identifier, getContext().getRegisterInfo(), S,
6015 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006016 return MatchOperand_Success;
6017 }
6018
6019 Index = matchACRegisterName(Identifier);
6020 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006021 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006022 Index, Identifier, getContext().getRegisterInfo(), S,
6023 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006024 return MatchOperand_Success;
6025 }
6026
6027 Index = matchMSA128RegisterName(Identifier);
6028 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006029 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006030 Index, Identifier, getContext().getRegisterInfo(), S,
6031 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006032 return MatchOperand_Success;
6033 }
6034
6035 Index = matchMSA128CtrlRegisterName(Identifier);
6036 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006037 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006038 Index, Identifier, getContext().getRegisterInfo(), S,
6039 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006040 return MatchOperand_Success;
6041 }
6042
6043 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006044}
6045
Alex Bradbury58eba092016-11-01 16:32:05 +00006046OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006047MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006048 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00006049 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006050
6051 if (Token.is(AsmToken::Identifier)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006052 LLVM_DEBUG(dbgs() << ".. identifier\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006053 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006054 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006055 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006056 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006057 } else if (Token.is(AsmToken::Integer)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006058 LLVM_DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006059 int64_t RegNum = Token.getIntVal();
6060 if (RegNum < 0 || RegNum > 31) {
6061 // Show the error, but treat invalid register
6062 // number as a normal one to continue parsing
6063 // and catch other possible errors.
6064 Error(getLexer().getLoc(), "invalid register number");
6065 }
Toma Tabacu13964452014-09-04 13:23:44 +00006066 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006067 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006068 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006069 return MatchOperand_Success;
6070 }
6071
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006072 LLVM_DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006073
6074 return MatchOperand_NoMatch;
6075}
6076
Alex Bradbury58eba092016-11-01 16:32:05 +00006077OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006078MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006079 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006080 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006081
6082 auto Token = Parser.getTok();
6083
6084 SMLoc S = Token.getLoc();
6085
6086 if (Token.isNot(AsmToken::Dollar)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006087 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006088 if (Token.is(AsmToken::Identifier)) {
6089 if (searchSymbolAlias(Operands))
6090 return MatchOperand_Success;
6091 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006092 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006093 return MatchOperand_NoMatch;
6094 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006095 LLVM_DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006096
Toma Tabacu13964452014-09-04 13:23:44 +00006097 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006098 if (ResTy == MatchOperand_Success) {
6099 Parser.Lex(); // $
6100 Parser.Lex(); // identifier
6101 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006102 return ResTy;
6103}
6104
Alex Bradbury58eba092016-11-01 16:32:05 +00006105OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006106MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006107 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006108 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006109
6110 SMLoc S = getLexer().getLoc();
6111
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006112 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006113 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006114 if (ResTy != MatchOperand_NoMatch)
6115 return ResTy;
6116
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006117 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006118 const MCExpr *Expr = nullptr;
6119 if (Parser.parseExpression(Expr)) {
6120 // We have no way of knowing if a symbol was consumed so we must ParseFail
6121 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006122 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006123 Operands.push_back(
6124 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006125 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006126}
6127
Alex Bradbury58eba092016-11-01 16:32:05 +00006128OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006129MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006130 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006131 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006132 // If the first token is '$' we may have register operand. We have to reject
6133 // cases where it is not a register. Complicating the matter is that
6134 // register names are not reserved across all ABIs.
6135 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006136 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006137 if (Parser.getTok().is(AsmToken::Dollar)) {
6138 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6139 ? MatchOperand_ParseFail
6140 : MatchOperand_NoMatch;
6141 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006142 if (getParser().parseExpression(IdVal))
6143 return MatchOperand_ParseFail;
6144 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006145 if (!MCE)
6146 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006147 int64_t Val = MCE->getValue();
6148 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6149 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006150 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006151 return MatchOperand_Success;
6152}
6153
Alex Bradbury58eba092016-11-01 16:32:05 +00006154OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006155MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6156 MCAsmParser &Parser = getParser();
6157 SmallVector<unsigned, 10> Regs;
6158 unsigned RegNo;
6159 unsigned PrevReg = Mips::NoRegister;
6160 bool RegRange = false;
6161 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6162
6163 if (Parser.getTok().isNot(AsmToken::Dollar))
6164 return MatchOperand_ParseFail;
6165
6166 SMLoc S = Parser.getTok().getLoc();
6167 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6168 SMLoc E = getLexer().getLoc();
6169 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6170 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6171 if (RegRange) {
6172 // Remove last register operand because registers from register range
6173 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006174 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6175 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006176 Regs.push_back(RegNo);
6177 } else {
6178 unsigned TmpReg = PrevReg + 1;
6179 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006180 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6181 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6182 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006183 Error(E, "invalid register operand");
6184 return MatchOperand_ParseFail;
6185 }
6186
6187 PrevReg = TmpReg;
6188 Regs.push_back(TmpReg++);
6189 }
6190 }
6191
6192 RegRange = false;
6193 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006194 if ((PrevReg == Mips::NoRegister) &&
6195 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6196 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006197 Error(E, "$16 or $31 expected");
6198 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006199 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6200 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6201 !isGP64bit()) ||
6202 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6203 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6204 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006205 Error(E, "invalid register operand");
6206 return MatchOperand_ParseFail;
6207 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006208 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6209 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6210 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006211 Error(E, "consecutive register numbers expected");
6212 return MatchOperand_ParseFail;
6213 }
6214
6215 Regs.push_back(RegNo);
6216 }
6217
6218 if (Parser.getTok().is(AsmToken::Minus))
6219 RegRange = true;
6220
6221 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6222 !Parser.getTok().isNot(AsmToken::Comma)) {
6223 Error(E, "',' or '-' expected");
6224 return MatchOperand_ParseFail;
6225 }
6226
6227 Lex(); // Consume comma or minus
6228 if (Parser.getTok().isNot(AsmToken::Dollar))
6229 break;
6230
6231 PrevReg = RegNo;
6232 }
6233
6234 SMLoc E = Parser.getTok().getLoc();
6235 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6236 parseMemOperand(Operands);
6237 return MatchOperand_Success;
6238}
6239
Alex Bradbury58eba092016-11-01 16:32:05 +00006240OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006241MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6242 MCAsmParser &Parser = getParser();
6243
6244 SMLoc S = Parser.getTok().getLoc();
6245 if (parseAnyRegister(Operands) != MatchOperand_Success)
6246 return MatchOperand_ParseFail;
6247
6248 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006249 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006250
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006251 Operands.pop_back();
6252 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006253 return MatchOperand_Success;
6254}
6255
Alex Bradbury58eba092016-11-01 16:32:05 +00006256OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006257MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6258 MCAsmParser &Parser = getParser();
6259 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6260 SmallVector<unsigned, 10> Regs;
6261
6262 if (Parser.getTok().isNot(AsmToken::Dollar))
6263 return MatchOperand_ParseFail;
6264
6265 SMLoc S = Parser.getTok().getLoc();
6266
6267 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6268 return MatchOperand_ParseFail;
6269
6270 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6271 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6272 Regs.push_back(RegNo);
6273
6274 SMLoc E = Parser.getTok().getLoc();
6275 if (Parser.getTok().isNot(AsmToken::Comma)) {
6276 Error(E, "',' expected");
6277 return MatchOperand_ParseFail;
6278 }
6279
6280 // Remove comma.
6281 Parser.Lex();
6282
6283 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6284 return MatchOperand_ParseFail;
6285
6286 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6287 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6288 Regs.push_back(RegNo);
6289
6290 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6291
6292 return MatchOperand_Success;
6293}
6294
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006295/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6296/// either this.
6297/// ::= '(', register, ')'
6298/// handle it before we iterate so we don't get tripped up by the lack of
6299/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006300bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006301 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006302 if (getLexer().is(AsmToken::LParen)) {
6303 Operands.push_back(
6304 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6305 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006306 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006307 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006308 return Error(Loc, "unexpected token in argument list");
6309 }
6310 if (Parser.getTok().isNot(AsmToken::RParen)) {
6311 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006312 return Error(Loc, "unexpected token, expected ')'");
6313 }
6314 Operands.push_back(
6315 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6316 Parser.Lex();
6317 }
6318 return false;
6319}
6320
6321/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6322/// either one of these.
6323/// ::= '[', register, ']'
6324/// ::= '[', integer, ']'
6325/// handle it before we iterate so we don't get tripped up by the lack of
6326/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006327bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006328 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006329 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006330 if (getLexer().is(AsmToken::LBrac)) {
6331 Operands.push_back(
6332 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6333 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006334 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006335 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006336 return Error(Loc, "unexpected token in argument list");
6337 }
6338 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6339 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006340 return Error(Loc, "unexpected token, expected ']'");
6341 }
6342 Operands.push_back(
6343 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6344 Parser.Lex();
6345 }
6346 return false;
6347}
6348
David Blaikie960ea3f2014-06-08 16:18:35 +00006349bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6350 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006351 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006352 LLVM_DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006353
6354 // We have reached first instruction, module directive are now forbidden.
6355 getTargetStreamer().forbidModuleDirective();
6356
Vladimir Medic74593e62013-07-17 15:00:42 +00006357 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006358 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006359 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006360 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006361 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006362 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006363
6364 // Read the remaining operands.
6365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6366 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006367 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006368 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006369 return Error(Loc, "unexpected token in argument list");
6370 }
Toma Tabacu13964452014-09-04 13:23:44 +00006371 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006372 return true;
6373 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006374
Jack Carterd0bd6422013-04-18 00:41:53 +00006375 while (getLexer().is(AsmToken::Comma)) {
6376 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006377 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006378 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006379 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006380 return Error(Loc, "unexpected token in argument list");
6381 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006382 // Parse bracket and parenthesis suffixes before we iterate
6383 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006384 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006385 return true;
6386 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006387 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006388 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006389 }
6390 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006391 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6392 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006393 return Error(Loc, "unexpected token in argument list");
6394 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006395 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006396 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006397}
6398
Nirav Dave996fc132016-05-05 14:15:46 +00006399// FIXME: Given that these have the same name, these should both be
6400// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006401bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006402 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006403 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006404}
6405
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006406bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006407 return Error(Loc, ErrorMsg);
6408}
6409
Jack Carter0b744b32012-10-04 02:29:46 +00006410bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006411 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006412 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006413
6414 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006415 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006416
6417 Parser.Lex(); // Eat "noat".
6418
Jack Carterd0bd6422013-04-18 00:41:53 +00006419 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006421 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006422 return false;
6423 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006424
6425 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006426 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006427 return false;
6428}
Jack Carterd0bd6422013-04-18 00:41:53 +00006429
Jack Carter0b744b32012-10-04 02:29:46 +00006430bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006431 // Line can be: ".set at", which sets $at to $1
6432 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006433 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006434 Parser.Lex(); // Eat "at".
6435
Jack Carter0b744b32012-10-04 02:29:46 +00006436 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006437 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006438 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006439
6440 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006441 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006442 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006443 }
6444
6445 if (getLexer().isNot(AsmToken::Equal)) {
6446 reportParseError("unexpected token, expected equals sign");
6447 return false;
6448 }
6449 Parser.Lex(); // Eat "=".
6450
6451 if (getLexer().isNot(AsmToken::Dollar)) {
6452 if (getLexer().is(AsmToken::EndOfStatement)) {
6453 reportParseError("no register specified");
6454 return false;
6455 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006456 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006457 return false;
6458 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006459 }
6460 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006461
Toma Tabacu16a74492015-02-13 10:30:57 +00006462 // Find out what "reg" is.
6463 unsigned AtRegNo;
6464 const AsmToken &Reg = Parser.getTok();
6465 if (Reg.is(AsmToken::Identifier)) {
6466 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6467 } else if (Reg.is(AsmToken::Integer)) {
6468 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006469 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006470 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006471 return false;
6472 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006473
6474 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006475 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006476 reportParseError("invalid register");
6477 return false;
6478 }
6479 Parser.Lex(); // Eat "reg".
6480
6481 // If this is not the end of the statement, report an error.
6482 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6483 reportParseError("unexpected token, expected end of statement");
6484 return false;
6485 }
6486
6487 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6488
6489 Parser.Lex(); // Consume the EndOfStatement.
6490 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006491}
6492
6493bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006494 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006495 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006496 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006497 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006498 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006499 return false;
6500 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006501 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006502 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006503 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006504 return false;
6505}
6506
6507bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006508 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006509 Parser.Lex();
6510 // If this is not the end of the statement, report an error.
6511 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006512 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006513 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006514 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006515 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006516 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006517 Parser.Lex(); // Consume the EndOfStatement.
6518 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006519}
6520
6521bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006522 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006523 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006524 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006525 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006526 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006527 return false;
6528 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006529 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006530 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006531 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006532 return false;
6533}
6534
6535bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006536 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006537 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006538 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006539 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006540 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006541 return false;
6542 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006543 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006544 reportParseError("`noreorder' must be set before `nomacro'");
6545 return false;
6546 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006547 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006548 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006549 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006550 return false;
6551}
Jack Carterd76b2372013-03-21 21:44:16 +00006552
Daniel Sanders44934432014-08-07 12:03:36 +00006553bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006554 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006555 Parser.Lex();
6556
6557 // If this is not the end of the statement, report an error.
6558 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006559 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006560
6561 setFeatureBits(Mips::FeatureMSA, "msa");
6562 getTargetStreamer().emitDirectiveSetMsa();
6563 return false;
6564}
6565
6566bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006567 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006568 Parser.Lex();
6569
6570 // If this is not the end of the statement, report an error.
6571 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006572 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006573
6574 clearFeatureBits(Mips::FeatureMSA, "msa");
6575 getTargetStreamer().emitDirectiveSetNoMsa();
6576 return false;
6577}
6578
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006579bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006580 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006581 Parser.Lex(); // Eat "nodsp".
6582
6583 // If this is not the end of the statement, report an error.
6584 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6585 reportParseError("unexpected token, expected end of statement");
6586 return false;
6587 }
6588
6589 clearFeatureBits(Mips::FeatureDSP, "dsp");
6590 getTargetStreamer().emitDirectiveSetNoDsp();
6591 return false;
6592}
6593
Toma Tabacucc2502d2014-11-04 17:18:07 +00006594bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006595 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006596 Parser.Lex(); // Eat "mips16".
6597
Jack Carter39536722014-01-22 23:08:42 +00006598 // If this is not the end of the statement, report an error.
6599 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006600 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006601 return false;
6602 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006603
6604 setFeatureBits(Mips::FeatureMips16, "mips16");
6605 getTargetStreamer().emitDirectiveSetMips16();
6606 Parser.Lex(); // Consume the EndOfStatement.
6607 return false;
6608}
6609
6610bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006611 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006612 Parser.Lex(); // Eat "nomips16".
6613
6614 // If this is not the end of the statement, report an error.
6615 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6616 reportParseError("unexpected token, expected end of statement");
6617 return false;
6618 }
6619
6620 clearFeatureBits(Mips::FeatureMips16, "mips16");
6621 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006622 Parser.Lex(); // Consume the EndOfStatement.
6623 return false;
6624}
6625
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006626bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006627 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006628 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006629 // Line can be: .set fp=32
6630 // .set fp=xx
6631 // .set fp=64
6632 Parser.Lex(); // Eat fp token
6633 AsmToken Tok = Parser.getTok();
6634 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006635 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006636 return false;
6637 }
6638 Parser.Lex(); // Eat '=' token.
6639 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006640
6641 if (!parseFpABIValue(FpAbiVal, ".set"))
6642 return false;
6643
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006644 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006645 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006646 return false;
6647 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006648 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006649 Parser.Lex(); // Consume the EndOfStatement.
6650 return false;
6651}
6652
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006653bool MipsAsmParser::parseSetOddSPRegDirective() {
6654 MCAsmParser &Parser = getParser();
6655
6656 Parser.Lex(); // Eat "oddspreg".
6657 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6658 reportParseError("unexpected token, expected end of statement");
6659 return false;
6660 }
6661
6662 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6663 getTargetStreamer().emitDirectiveSetOddSPReg();
6664 return false;
6665}
6666
6667bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6668 MCAsmParser &Parser = getParser();
6669
6670 Parser.Lex(); // Eat "nooddspreg".
6671 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6672 reportParseError("unexpected token, expected end of statement");
6673 return false;
6674 }
6675
6676 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6677 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6678 return false;
6679}
6680
Simon Dardis805f1e02017-07-11 21:28:36 +00006681bool MipsAsmParser::parseSetMtDirective() {
6682 MCAsmParser &Parser = getParser();
6683 Parser.Lex(); // Eat "mt".
6684
6685 // If this is not the end of the statement, report an error.
6686 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6687 reportParseError("unexpected token, expected end of statement");
6688 return false;
6689 }
6690
6691 setFeatureBits(Mips::FeatureMT, "mt");
6692 getTargetStreamer().emitDirectiveSetMt();
6693 Parser.Lex(); // Consume the EndOfStatement.
6694 return false;
6695}
6696
6697bool MipsAsmParser::parseSetNoMtDirective() {
6698 MCAsmParser &Parser = getParser();
6699 Parser.Lex(); // Eat "nomt".
6700
6701 // If this is not the end of the statement, report an error.
6702 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6703 reportParseError("unexpected token, expected end of statement");
6704 return false;
6705 }
6706
6707 clearFeatureBits(Mips::FeatureMT, "mt");
6708
6709 getTargetStreamer().emitDirectiveSetNoMt();
6710 Parser.Lex(); // Consume the EndOfStatement.
6711 return false;
6712}
6713
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006714bool MipsAsmParser::parseSetNoCRCDirective() {
6715 MCAsmParser &Parser = getParser();
6716 Parser.Lex(); // Eat "nocrc".
6717
6718 // If this is not the end of the statement, report an error.
6719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6720 reportParseError("unexpected token, expected end of statement");
6721 return false;
6722 }
6723
6724 clearFeatureBits(Mips::FeatureCRC, "crc");
6725
6726 getTargetStreamer().emitDirectiveSetNoCRC();
6727 Parser.Lex(); // Consume the EndOfStatement.
6728 return false;
6729}
6730
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006731bool MipsAsmParser::parseSetNoVirtDirective() {
6732 MCAsmParser &Parser = getParser();
6733 Parser.Lex(); // Eat "novirt".
6734
6735 // If this is not the end of the statement, report an error.
6736 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6737 reportParseError("unexpected token, expected end of statement");
6738 return false;
6739 }
6740
6741 clearFeatureBits(Mips::FeatureVirt, "virt");
6742
6743 getTargetStreamer().emitDirectiveSetNoVirt();
6744 Parser.Lex(); // Consume the EndOfStatement.
6745 return false;
6746}
6747
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006748bool MipsAsmParser::parseSetNoGINVDirective() {
6749 MCAsmParser &Parser = getParser();
6750 Parser.Lex(); // Eat "noginv".
6751
6752 // If this is not the end of the statement, report an error.
6753 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6754 reportParseError("unexpected token, expected end of statement");
6755 return false;
6756 }
6757
6758 clearFeatureBits(Mips::FeatureGINV, "ginv");
6759
6760 getTargetStreamer().emitDirectiveSetNoGINV();
6761 Parser.Lex(); // Consume the EndOfStatement.
6762 return false;
6763}
6764
Toma Tabacu9db22db2014-09-09 10:15:38 +00006765bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006766 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006767 SMLoc Loc = getLexer().getLoc();
6768
6769 Parser.Lex();
6770 if (getLexer().isNot(AsmToken::EndOfStatement))
6771 return reportParseError("unexpected token, expected end of statement");
6772
6773 // Always keep an element on the options "stack" to prevent the user
6774 // from changing the initial options. This is how we remember them.
6775 if (AssemblerOptions.size() == 2)
6776 return reportParseError(Loc, ".set pop with no .set push");
6777
Akira Hatanakab11ef082015-11-14 06:35:56 +00006778 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006779 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006780 setAvailableFeatures(
6781 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6782 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006783
6784 getTargetStreamer().emitDirectiveSetPop();
6785 return false;
6786}
6787
6788bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006789 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006790 Parser.Lex();
6791 if (getLexer().isNot(AsmToken::EndOfStatement))
6792 return reportParseError("unexpected token, expected end of statement");
6793
6794 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006795 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006796 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006797
6798 getTargetStreamer().emitDirectiveSetPush();
6799 return false;
6800}
6801
Toma Tabacu29696502015-06-02 09:48:04 +00006802bool MipsAsmParser::parseSetSoftFloatDirective() {
6803 MCAsmParser &Parser = getParser();
6804 Parser.Lex();
6805 if (getLexer().isNot(AsmToken::EndOfStatement))
6806 return reportParseError("unexpected token, expected end of statement");
6807
6808 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6809 getTargetStreamer().emitDirectiveSetSoftFloat();
6810 return false;
6811}
6812
6813bool MipsAsmParser::parseSetHardFloatDirective() {
6814 MCAsmParser &Parser = getParser();
6815 Parser.Lex();
6816 if (getLexer().isNot(AsmToken::EndOfStatement))
6817 return reportParseError("unexpected token, expected end of statement");
6818
6819 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6820 getTargetStreamer().emitDirectiveSetHardFloat();
6821 return false;
6822}
6823
Jack Carterd76b2372013-03-21 21:44:16 +00006824bool MipsAsmParser::parseSetAssignment() {
6825 StringRef Name;
6826 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006827 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006828
6829 if (Parser.parseIdentifier(Name))
6830 reportParseError("expected identifier after .set");
6831
6832 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006833 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006834 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006835
Jack Carter3b2c96e2014-01-22 23:31:38 +00006836 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006837 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006838
Jim Grosbach6f482002015-05-18 18:43:14 +00006839 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006840 Sym->setVariableValue(Value);
6841
6842 return false;
6843}
Jack Carterd0bd6422013-04-18 00:41:53 +00006844
Toma Tabacu26647792014-09-09 12:52:14 +00006845bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006846 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006847 Parser.Lex();
6848 if (getLexer().isNot(AsmToken::EndOfStatement))
6849 return reportParseError("unexpected token, expected end of statement");
6850
6851 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006852 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006853 setAvailableFeatures(
6854 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6855 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006856 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6857
6858 getTargetStreamer().emitDirectiveSetMips0();
6859 return false;
6860}
6861
Toma Tabacu85618b32014-08-19 14:22:52 +00006862bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006863 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006864 Parser.Lex();
6865 if (getLexer().isNot(AsmToken::Equal))
6866 return reportParseError("unexpected token, expected equals sign");
6867
6868 Parser.Lex();
6869 StringRef Arch;
6870 if (Parser.parseIdentifier(Arch))
6871 return reportParseError("expected arch identifier");
6872
6873 StringRef ArchFeatureName =
6874 StringSwitch<StringRef>(Arch)
6875 .Case("mips1", "mips1")
6876 .Case("mips2", "mips2")
6877 .Case("mips3", "mips3")
6878 .Case("mips4", "mips4")
6879 .Case("mips5", "mips5")
6880 .Case("mips32", "mips32")
6881 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006882 .Case("mips32r3", "mips32r3")
6883 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006884 .Case("mips32r6", "mips32r6")
6885 .Case("mips64", "mips64")
6886 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006887 .Case("mips64r3", "mips64r3")
6888 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006889 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006890 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006891 .Case("r4000", "mips3") // This is an implementation of Mips3.
6892 .Default("");
6893
6894 if (ArchFeatureName.empty())
6895 return reportParseError("unsupported architecture");
6896
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006897 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6898 return reportParseError("mips64r6 does not support microMIPS");
6899
Toma Tabacu85618b32014-08-19 14:22:52 +00006900 selectArch(ArchFeatureName);
6901 getTargetStreamer().emitDirectiveSetArch(Arch);
6902 return false;
6903}
6904
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006905bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006906 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006907 Parser.Lex();
6908 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006909 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006910
Matheus Almeida2852af82014-04-22 10:15:54 +00006911 switch (Feature) {
6912 default:
6913 llvm_unreachable("Unimplemented feature");
6914 case Mips::FeatureDSP:
6915 setFeatureBits(Mips::FeatureDSP, "dsp");
6916 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006917 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006918 case Mips::FeatureDSPR2:
6919 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6920 getTargetStreamer().emitDirectiveSetDspr2();
6921 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006922 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006923 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006924 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006925 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006926 case Mips::FeatureMips1:
6927 selectArch("mips1");
6928 getTargetStreamer().emitDirectiveSetMips1();
6929 break;
6930 case Mips::FeatureMips2:
6931 selectArch("mips2");
6932 getTargetStreamer().emitDirectiveSetMips2();
6933 break;
6934 case Mips::FeatureMips3:
6935 selectArch("mips3");
6936 getTargetStreamer().emitDirectiveSetMips3();
6937 break;
6938 case Mips::FeatureMips4:
6939 selectArch("mips4");
6940 getTargetStreamer().emitDirectiveSetMips4();
6941 break;
6942 case Mips::FeatureMips5:
6943 selectArch("mips5");
6944 getTargetStreamer().emitDirectiveSetMips5();
6945 break;
6946 case Mips::FeatureMips32:
6947 selectArch("mips32");
6948 getTargetStreamer().emitDirectiveSetMips32();
6949 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006950 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006951 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006952 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006953 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006954 case Mips::FeatureMips32r3:
6955 selectArch("mips32r3");
6956 getTargetStreamer().emitDirectiveSetMips32R3();
6957 break;
6958 case Mips::FeatureMips32r5:
6959 selectArch("mips32r5");
6960 getTargetStreamer().emitDirectiveSetMips32R5();
6961 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006962 case Mips::FeatureMips32r6:
6963 selectArch("mips32r6");
6964 getTargetStreamer().emitDirectiveSetMips32R6();
6965 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006966 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006967 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006968 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006969 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006970 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006971 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006972 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006973 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006974 case Mips::FeatureMips64r3:
6975 selectArch("mips64r3");
6976 getTargetStreamer().emitDirectiveSetMips64R3();
6977 break;
6978 case Mips::FeatureMips64r5:
6979 selectArch("mips64r5");
6980 getTargetStreamer().emitDirectiveSetMips64R5();
6981 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006982 case Mips::FeatureMips64r6:
6983 selectArch("mips64r6");
6984 getTargetStreamer().emitDirectiveSetMips64R6();
6985 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006986 case Mips::FeatureCRC:
6987 setFeatureBits(Mips::FeatureCRC, "crc");
6988 getTargetStreamer().emitDirectiveSetCRC();
6989 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006990 case Mips::FeatureVirt:
6991 setFeatureBits(Mips::FeatureVirt, "virt");
6992 getTargetStreamer().emitDirectiveSetVirt();
6993 break;
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006994 case Mips::FeatureGINV:
6995 setFeatureBits(Mips::FeatureGINV, "ginv");
6996 getTargetStreamer().emitDirectiveSetGINV();
6997 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006998 }
6999 return false;
7000}
7001
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007002bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007003 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007004 if (getLexer().isNot(AsmToken::Comma)) {
7005 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007006 return Error(Loc, ErrorStr);
7007 }
7008
Matheus Almeida2852af82014-04-22 10:15:54 +00007009 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007010 return true;
7011}
7012
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007013// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7014// In this class, it is only used for .cprestore.
7015// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7016// MipsTargetELFStreamer and MipsAsmParser.
7017bool MipsAsmParser::isPicAndNotNxxAbi() {
7018 return inPicMode() && !(isABI_N32() || isABI_N64());
7019}
7020
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007021bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00007022 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00007023 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007024
Toma Tabacudde4c462014-11-06 10:02:45 +00007025 if (inMips16Mode()) {
7026 reportParseError(".cpload is not supported in Mips16 mode");
7027 return false;
7028 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007029
David Blaikie960ea3f2014-06-08 16:18:35 +00007030 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007031 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007032 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7033 reportParseError("expected register containing function address");
7034 return false;
7035 }
7036
David Blaikie960ea3f2014-06-08 16:18:35 +00007037 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7038 if (!RegOpnd.isGPRAsmReg()) {
7039 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007040 return false;
7041 }
7042
Toma Tabacudde4c462014-11-06 10:02:45 +00007043 // If this is not the end of the statement, report an error.
7044 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7045 reportParseError("unexpected token, expected end of statement");
7046 return false;
7047 }
7048
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007049 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007050 return false;
7051}
7052
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007053bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7054 MCAsmParser &Parser = getParser();
7055
7056 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7057 // is used in non-PIC mode.
7058
7059 if (inMips16Mode()) {
7060 reportParseError(".cprestore is not supported in Mips16 mode");
7061 return false;
7062 }
7063
7064 // Get the stack offset value.
7065 const MCExpr *StackOffset;
7066 int64_t StackOffsetVal;
7067 if (Parser.parseExpression(StackOffset)) {
7068 reportParseError("expected stack offset value");
7069 return false;
7070 }
7071
7072 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7073 reportParseError("stack offset is not an absolute expression");
7074 return false;
7075 }
7076
7077 if (StackOffsetVal < 0) {
7078 Warning(Loc, ".cprestore with negative stack offset has no effect");
7079 IsCpRestoreSet = false;
7080 } else {
7081 IsCpRestoreSet = true;
7082 CpRestoreOffset = StackOffsetVal;
7083 }
7084
7085 // If this is not the end of the statement, report an error.
7086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7087 reportParseError("unexpected token, expected end of statement");
7088 return false;
7089 }
7090
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007091 if (!getTargetStreamer().emitDirectiveCpRestore(
7092 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007093 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007094 Parser.Lex(); // Consume the EndOfStatement.
7095 return false;
7096}
7097
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007098bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007099 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007100 unsigned FuncReg;
7101 unsigned Save;
7102 bool SaveIsReg = true;
7103
Matheus Almeida7e815762014-06-18 13:08:59 +00007104 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007105 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007106 if (ResTy == MatchOperand_NoMatch) {
7107 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007108 return false;
7109 }
7110
7111 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7112 if (!FuncRegOpnd.isGPRAsmReg()) {
7113 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007114 return false;
7115 }
7116
7117 FuncReg = FuncRegOpnd.getGPR32Reg();
7118 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007119
Toma Tabacu65f10572014-09-16 15:00:52 +00007120 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007121 return true;
7122
Toma Tabacu13964452014-09-04 13:23:44 +00007123 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007124 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007125 const MCExpr *OffsetExpr;
7126 int64_t OffsetVal;
7127 SMLoc ExprLoc = getLexer().getLoc();
7128
7129 if (Parser.parseExpression(OffsetExpr) ||
7130 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7131 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007132 return false;
7133 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007134
7135 Save = OffsetVal;
7136 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007137 } else {
7138 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7139 if (!SaveOpnd.isGPRAsmReg()) {
7140 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007141 return false;
7142 }
7143 Save = SaveOpnd.getGPR32Reg();
7144 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007145
Toma Tabacu65f10572014-09-16 15:00:52 +00007146 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007147 return true;
7148
Toma Tabacu8874eac2015-02-18 13:46:53 +00007149 const MCExpr *Expr;
7150 if (Parser.parseExpression(Expr)) {
7151 reportParseError("expected expression");
7152 return false;
7153 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007154
Toma Tabacu8874eac2015-02-18 13:46:53 +00007155 if (Expr->getKind() != MCExpr::SymbolRef) {
7156 reportParseError("expected symbol");
7157 return false;
7158 }
7159 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7160
Daniel Sandersf173dda2015-09-22 10:50:09 +00007161 CpSaveLocation = Save;
7162 CpSaveLocationIsRegister = SaveIsReg;
7163
Toma Tabacu8874eac2015-02-18 13:46:53 +00007164 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7165 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007166 return false;
7167}
7168
Daniel Sandersf173dda2015-09-22 10:50:09 +00007169bool MipsAsmParser::parseDirectiveCPReturn() {
7170 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7171 CpSaveLocationIsRegister);
7172 return false;
7173}
7174
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007175bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007176 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007177 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7178 const AsmToken &Tok = Parser.getTok();
7179
7180 if (Tok.getString() == "2008") {
7181 Parser.Lex();
7182 getTargetStreamer().emitDirectiveNaN2008();
7183 return false;
7184 } else if (Tok.getString() == "legacy") {
7185 Parser.Lex();
7186 getTargetStreamer().emitDirectiveNaNLegacy();
7187 return false;
7188 }
7189 }
7190 // If we don't recognize the option passed to the .nan
7191 // directive (e.g. no option or unknown option), emit an error.
7192 reportParseError("invalid option in .nan directive");
7193 return false;
7194}
7195
Jack Carter0b744b32012-10-04 02:29:46 +00007196bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007197 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00007198 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00007199 const AsmToken &Tok = Parser.getTok();
7200
7201 if (Tok.getString() == "noat") {
7202 return parseSetNoAtDirective();
7203 } else if (Tok.getString() == "at") {
7204 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00007205 } else if (Tok.getString() == "arch") {
7206 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00007207 } else if (Tok.getString() == "bopt") {
7208 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
7209 getParser().Lex();
7210 return false;
7211 } else if (Tok.getString() == "nobopt") {
7212 // We're already running in nobopt mode, so nothing to do.
7213 getParser().Lex();
7214 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007215 } else if (Tok.getString() == "fp") {
7216 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007217 } else if (Tok.getString() == "oddspreg") {
7218 return parseSetOddSPRegDirective();
7219 } else if (Tok.getString() == "nooddspreg") {
7220 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00007221 } else if (Tok.getString() == "pop") {
7222 return parseSetPopDirective();
7223 } else if (Tok.getString() == "push") {
7224 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00007225 } else if (Tok.getString() == "reorder") {
7226 return parseSetReorderDirective();
7227 } else if (Tok.getString() == "noreorder") {
7228 return parseSetNoReorderDirective();
7229 } else if (Tok.getString() == "macro") {
7230 return parseSetMacroDirective();
7231 } else if (Tok.getString() == "nomacro") {
7232 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00007233 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00007234 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007235 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00007236 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007237 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007238 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007239 getTargetStreamer().emitDirectiveSetNoMicroMips();
7240 Parser.eatToEndOfStatement();
7241 return false;
7242 } else if (Tok.getString() == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007243 if (hasMips64r6()) {
7244 Error(Tok.getLoc(), ".set micromips directive is not supported with MIPS64R6");
7245 return false;
7246 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007247 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00007248 } else if (Tok.getString() == "mips0") {
7249 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00007250 } else if (Tok.getString() == "mips1") {
7251 return parseSetFeature(Mips::FeatureMips1);
7252 } else if (Tok.getString() == "mips2") {
7253 return parseSetFeature(Mips::FeatureMips2);
7254 } else if (Tok.getString() == "mips3") {
7255 return parseSetFeature(Mips::FeatureMips3);
7256 } else if (Tok.getString() == "mips4") {
7257 return parseSetFeature(Mips::FeatureMips4);
7258 } else if (Tok.getString() == "mips5") {
7259 return parseSetFeature(Mips::FeatureMips5);
7260 } else if (Tok.getString() == "mips32") {
7261 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00007262 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007263 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007264 } else if (Tok.getString() == "mips32r3") {
7265 return parseSetFeature(Mips::FeatureMips32r3);
7266 } else if (Tok.getString() == "mips32r5") {
7267 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007268 } else if (Tok.getString() == "mips32r6") {
7269 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007270 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007271 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007272 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007273 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007274 } else if (Tok.getString() == "mips64r3") {
7275 return parseSetFeature(Mips::FeatureMips64r3);
7276 } else if (Tok.getString() == "mips64r5") {
7277 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007278 } else if (Tok.getString() == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007279 if (inMicroMipsMode()) {
7280 Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS");
7281 return false;
7282 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007283 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00007284 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007285 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00007286 } else if (Tok.getString() == "dspr2") {
7287 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00007288 } else if (Tok.getString() == "nodsp") {
7289 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00007290 } else if (Tok.getString() == "msa") {
7291 return parseSetMsaDirective();
7292 } else if (Tok.getString() == "nomsa") {
7293 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00007294 } else if (Tok.getString() == "mt") {
7295 return parseSetMtDirective();
7296 } else if (Tok.getString() == "nomt") {
7297 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00007298 } else if (Tok.getString() == "softfloat") {
7299 return parseSetSoftFloatDirective();
7300 } else if (Tok.getString() == "hardfloat") {
7301 return parseSetHardFloatDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007302 } else if (Tok.getString() == "crc") {
7303 return parseSetFeature(Mips::FeatureCRC);
7304 } else if (Tok.getString() == "nocrc") {
7305 return parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007306 } else if (Tok.getString() == "virt") {
7307 return parseSetFeature(Mips::FeatureVirt);
7308 } else if (Tok.getString() == "novirt") {
7309 return parseSetNoVirtDirective();
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007310 } else if (Tok.getString() == "ginv") {
7311 return parseSetFeature(Mips::FeatureGINV);
7312 } else if (Tok.getString() == "noginv") {
7313 return parseSetNoGINVDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00007314 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00007315 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00007316 parseSetAssignment();
7317 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00007318 }
Jack Carter07c818d2013-01-25 01:31:34 +00007319
Jack Carter0b744b32012-10-04 02:29:46 +00007320 return true;
7321}
7322
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007323/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007324/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007325bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007326 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007327 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007328 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007329 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007330 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007331 return true;
7332
7333 getParser().getStreamer().EmitValue(Value, Size);
7334
7335 if (getLexer().is(AsmToken::EndOfStatement))
7336 break;
7337
Jack Carter07c818d2013-01-25 01:31:34 +00007338 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007339 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007340 Parser.Lex();
7341 }
7342 }
7343
7344 Parser.Lex();
7345 return false;
7346}
7347
Vladimir Medic4c299852013-11-06 11:27:05 +00007348/// parseDirectiveGpWord
7349/// ::= .gpword local_sym
7350bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007351 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007352 const MCExpr *Value;
7353 // EmitGPRel32Value requires an expression, so we are using base class
7354 // method to evaluate the expression.
7355 if (getParser().parseExpression(Value))
7356 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007357 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007358
Vladimir Medice10c1122013-11-13 13:18:04 +00007359 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007360 return Error(getLexer().getLoc(),
7361 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007362 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007363 return false;
7364}
7365
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007366/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007367/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007368bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007369 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007370 const MCExpr *Value;
7371 // EmitGPRel64Value requires an expression, so we are using base class
7372 // method to evaluate the expression.
7373 if (getParser().parseExpression(Value))
7374 return true;
7375 getParser().getStreamer().EmitGPRel64Value(Value);
7376
7377 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007378 return Error(getLexer().getLoc(),
7379 "unexpected token, expected end of statement");
7380 Parser.Lex(); // Eat EndOfStatement token.
7381 return false;
7382}
7383
7384/// parseDirectiveDtpRelWord
7385/// ::= .dtprelword tls_sym
7386bool MipsAsmParser::parseDirectiveDtpRelWord() {
7387 MCAsmParser &Parser = getParser();
7388 const MCExpr *Value;
7389 // EmitDTPRel32Value requires an expression, so we are using base class
7390 // method to evaluate the expression.
7391 if (getParser().parseExpression(Value))
7392 return true;
7393 getParser().getStreamer().EmitDTPRel32Value(Value);
7394
7395 if (getLexer().isNot(AsmToken::EndOfStatement))
7396 return Error(getLexer().getLoc(),
7397 "unexpected token, expected end of statement");
7398 Parser.Lex(); // Eat EndOfStatement token.
7399 return false;
7400}
7401
7402/// parseDirectiveDtpRelDWord
7403/// ::= .dtpreldword tls_sym
7404bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7405 MCAsmParser &Parser = getParser();
7406 const MCExpr *Value;
7407 // EmitDTPRel64Value requires an expression, so we are using base class
7408 // method to evaluate the expression.
7409 if (getParser().parseExpression(Value))
7410 return true;
7411 getParser().getStreamer().EmitDTPRel64Value(Value);
7412
7413 if (getLexer().isNot(AsmToken::EndOfStatement))
7414 return Error(getLexer().getLoc(),
7415 "unexpected token, expected end of statement");
7416 Parser.Lex(); // Eat EndOfStatement token.
7417 return false;
7418}
7419
7420/// parseDirectiveTpRelWord
7421/// ::= .tprelword tls_sym
7422bool MipsAsmParser::parseDirectiveTpRelWord() {
7423 MCAsmParser &Parser = getParser();
7424 const MCExpr *Value;
7425 // EmitTPRel32Value requires an expression, so we are using base class
7426 // method to evaluate the expression.
7427 if (getParser().parseExpression(Value))
7428 return true;
7429 getParser().getStreamer().EmitTPRel32Value(Value);
7430
7431 if (getLexer().isNot(AsmToken::EndOfStatement))
7432 return Error(getLexer().getLoc(),
7433 "unexpected token, expected end of statement");
7434 Parser.Lex(); // Eat EndOfStatement token.
7435 return false;
7436}
7437
7438/// parseDirectiveTpRelDWord
7439/// ::= .tpreldword tls_sym
7440bool MipsAsmParser::parseDirectiveTpRelDWord() {
7441 MCAsmParser &Parser = getParser();
7442 const MCExpr *Value;
7443 // EmitTPRel64Value requires an expression, so we are using base class
7444 // method to evaluate the expression.
7445 if (getParser().parseExpression(Value))
7446 return true;
7447 getParser().getStreamer().EmitTPRel64Value(Value);
7448
7449 if (getLexer().isNot(AsmToken::EndOfStatement))
7450 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007451 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007452 Parser.Lex(); // Eat EndOfStatement token.
7453 return false;
7454}
7455
Jack Carter0cd3c192014-01-06 23:27:31 +00007456bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007457 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007458 // Get the option token.
7459 AsmToken Tok = Parser.getTok();
7460 // At the moment only identifiers are supported.
7461 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007462 return Error(Parser.getTok().getLoc(),
7463 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007464 }
7465
7466 StringRef Option = Tok.getIdentifier();
7467
7468 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007469 // MipsAsmParser needs to know if the current PIC mode changes.
7470 IsPicEnabled = false;
7471
Jack Carter0cd3c192014-01-06 23:27:31 +00007472 getTargetStreamer().emitDirectiveOptionPic0();
7473 Parser.Lex();
7474 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007475 return Error(Parser.getTok().getLoc(),
7476 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007477 }
7478 return false;
7479 }
7480
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007481 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007482 // MipsAsmParser needs to know if the current PIC mode changes.
7483 IsPicEnabled = true;
7484
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007485 getTargetStreamer().emitDirectiveOptionPic2();
7486 Parser.Lex();
7487 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007488 return Error(Parser.getTok().getLoc(),
7489 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007490 }
7491 return false;
7492 }
7493
Jack Carter0cd3c192014-01-06 23:27:31 +00007494 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007495 Warning(Parser.getTok().getLoc(),
7496 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007497 Parser.eatToEndOfStatement();
7498 return false;
7499}
7500
Toma Tabacu9ca50962015-04-16 09:53:47 +00007501/// parseInsnDirective
7502/// ::= .insn
7503bool MipsAsmParser::parseInsnDirective() {
7504 // If this is not the end of the statement, report an error.
7505 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7506 reportParseError("unexpected token, expected end of statement");
7507 return false;
7508 }
7509
7510 // The actual label marking happens in
7511 // MipsELFStreamer::createPendingLabelRelocs().
7512 getTargetStreamer().emitDirectiveInsn();
7513
7514 getParser().Lex(); // Eat EndOfStatement token.
7515 return false;
7516}
7517
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007518/// parseRSectionDirective
7519/// ::= .rdata
7520bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
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 MCSection *ELFSection = getContext().getELFSection(
7528 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7529 getParser().getStreamer().SwitchSection(ELFSection);
7530
7531 getParser().Lex(); // Eat EndOfStatement token.
7532 return false;
7533}
7534
Simon Atanasyanbe186202016-02-11 06:45:54 +00007535/// parseSSectionDirective
7536/// ::= .sbss
7537/// ::= .sdata
7538bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7539 // If this is not the end of the statement, report an error.
7540 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7541 reportParseError("unexpected token, expected end of statement");
7542 return false;
7543 }
7544
7545 MCSection *ELFSection = getContext().getELFSection(
7546 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7547 getParser().getStreamer().SwitchSection(ELFSection);
7548
7549 getParser().Lex(); // Eat EndOfStatement token.
7550 return false;
7551}
7552
Daniel Sanders7e527422014-07-10 13:38:23 +00007553/// parseDirectiveModule
7554/// ::= .module oddspreg
7555/// ::= .module nooddspreg
7556/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007557/// ::= .module softfloat
7558/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007559/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007560/// ::= .module crc
7561/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007562/// ::= .module virt
7563/// ::= .module novirt
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007564/// ::= .module ginv
7565/// ::= .module noginv
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007566bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007567 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007568 MCAsmLexer &Lexer = getLexer();
7569 SMLoc L = Lexer.getLoc();
7570
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007571 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007572 // TODO : get a better message.
7573 reportParseError(".module directive must appear before any code");
7574 return false;
7575 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007576
Toma Tabacuc405c822015-01-23 10:40:19 +00007577 StringRef Option;
7578 if (Parser.parseIdentifier(Option)) {
7579 reportParseError("expected .module option identifier");
7580 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007581 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007582
Toma Tabacuc405c822015-01-23 10:40:19 +00007583 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007584 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007585
Toma Tabacu3c499582015-06-25 10:56:57 +00007586 // Synchronize the abiflags information with the FeatureBits information we
7587 // changed above.
7588 getTargetStreamer().updateABIInfo(*this);
7589
7590 // If printing assembly, use the recently updated abiflags information.
7591 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7592 // emitted at the end).
7593 getTargetStreamer().emitDirectiveModuleOddSPReg();
7594
Toma Tabacuc405c822015-01-23 10:40:19 +00007595 // If this is not the end of the statement, report an error.
7596 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7597 reportParseError("unexpected token, expected end of statement");
7598 return false;
7599 }
7600
7601 return false; // parseDirectiveModule has finished successfully.
7602 } else if (Option == "nooddspreg") {
7603 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007604 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007605 }
7606
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007607 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007608
Toma Tabacu3c499582015-06-25 10:56:57 +00007609 // Synchronize the abiflags information with the FeatureBits information we
7610 // changed above.
7611 getTargetStreamer().updateABIInfo(*this);
7612
7613 // If printing assembly, use the recently updated abiflags information.
7614 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7615 // emitted at the end).
7616 getTargetStreamer().emitDirectiveModuleOddSPReg();
7617
Toma Tabacuc405c822015-01-23 10:40:19 +00007618 // If this is not the end of the statement, report an error.
7619 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7620 reportParseError("unexpected token, expected end of statement");
7621 return false;
7622 }
7623
7624 return false; // parseDirectiveModule has finished successfully.
7625 } else if (Option == "fp") {
7626 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007627 } else if (Option == "softfloat") {
7628 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7629
7630 // Synchronize the ABI Flags information with the FeatureBits information we
7631 // updated above.
7632 getTargetStreamer().updateABIInfo(*this);
7633
7634 // If printing assembly, use the recently updated ABI Flags information.
7635 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7636 // emitted later).
7637 getTargetStreamer().emitDirectiveModuleSoftFloat();
7638
7639 // If this is not the end of the statement, report an error.
7640 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7641 reportParseError("unexpected token, expected end of statement");
7642 return false;
7643 }
7644
7645 return false; // parseDirectiveModule has finished successfully.
7646 } else if (Option == "hardfloat") {
7647 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7648
7649 // Synchronize the ABI Flags information with the FeatureBits information we
7650 // updated above.
7651 getTargetStreamer().updateABIInfo(*this);
7652
7653 // If printing assembly, use the recently updated ABI Flags information.
7654 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7655 // emitted later).
7656 getTargetStreamer().emitDirectiveModuleHardFloat();
7657
7658 // If this is not the end of the statement, report an error.
7659 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7660 reportParseError("unexpected token, expected end of statement");
7661 return false;
7662 }
7663
7664 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007665 } else if (Option == "mt") {
7666 setModuleFeatureBits(Mips::FeatureMT, "mt");
7667
7668 // Synchronize the ABI Flags information with the FeatureBits information we
7669 // updated above.
7670 getTargetStreamer().updateABIInfo(*this);
7671
Simon Dardisd9611922017-07-11 21:36:58 +00007672 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007673 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7674 // emitted later).
7675 getTargetStreamer().emitDirectiveModuleMT();
7676
7677 // If this is not the end of the statement, report an error.
7678 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7679 reportParseError("unexpected token, expected end of statement");
7680 return false;
7681 }
7682
7683 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007684 } else if (Option == "crc") {
7685 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7686
7687 // Synchronize the ABI Flags information with the FeatureBits information we
7688 // updated above.
7689 getTargetStreamer().updateABIInfo(*this);
7690
7691 // If printing assembly, use the recently updated ABI Flags information.
7692 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7693 // emitted later).
7694 getTargetStreamer().emitDirectiveModuleCRC();
7695
7696 // If this is not the end of the statement, report an error.
7697 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7698 reportParseError("unexpected token, expected end of statement");
7699 return false;
7700 }
7701
7702 return false; // parseDirectiveModule has finished successfully.
7703 } else if (Option == "nocrc") {
7704 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7705
7706 // Synchronize the ABI Flags information with the FeatureBits information we
7707 // updated above.
7708 getTargetStreamer().updateABIInfo(*this);
7709
7710 // If printing assembly, use the recently updated ABI Flags information.
7711 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7712 // emitted later).
7713 getTargetStreamer().emitDirectiveModuleNoCRC();
7714
7715 // If this is not the end of the statement, report an error.
7716 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7717 reportParseError("unexpected token, expected end of statement");
7718 return false;
7719 }
7720
7721 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007722 } else if (Option == "virt") {
7723 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7724
7725 // Synchronize the ABI Flags information with the FeatureBits information we
7726 // updated above.
7727 getTargetStreamer().updateABIInfo(*this);
7728
7729 // If printing assembly, use the recently updated ABI Flags information.
7730 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7731 // emitted later).
7732 getTargetStreamer().emitDirectiveModuleVirt();
7733
7734 // If this is not the end of the statement, report an error.
7735 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7736 reportParseError("unexpected token, expected end of statement");
7737 return false;
7738 }
7739
7740 return false; // parseDirectiveModule has finished successfully.
7741 } else if (Option == "novirt") {
7742 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7743
7744 // Synchronize the ABI Flags information with the FeatureBits information we
7745 // updated above.
7746 getTargetStreamer().updateABIInfo(*this);
7747
7748 // If printing assembly, use the recently updated ABI Flags information.
7749 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7750 // emitted later).
7751 getTargetStreamer().emitDirectiveModuleNoVirt();
7752
7753 // If this is not the end of the statement, report an error.
7754 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7755 reportParseError("unexpected token, expected end of statement");
7756 return false;
7757 }
7758
7759 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007760 } else if (Option == "ginv") {
7761 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
7762
7763 // Synchronize the ABI Flags information with the FeatureBits information we
7764 // updated above.
7765 getTargetStreamer().updateABIInfo(*this);
7766
7767 // If printing assembly, use the recently updated ABI Flags information.
7768 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7769 // emitted later).
7770 getTargetStreamer().emitDirectiveModuleGINV();
7771
7772 // If this is not the end of the statement, report an error.
7773 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7774 reportParseError("unexpected token, expected end of statement");
7775 return false;
7776 }
7777
7778 return false; // parseDirectiveModule has finished successfully.
7779 } else if (Option == "noginv") {
7780 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
7781
7782 // Synchronize the ABI Flags information with the FeatureBits information we
7783 // updated above.
7784 getTargetStreamer().updateABIInfo(*this);
7785
7786 // If printing assembly, use the recently updated ABI Flags information.
7787 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7788 // emitted later).
7789 getTargetStreamer().emitDirectiveModuleNoGINV();
7790
7791 // If this is not the end of the statement, report an error.
7792 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7793 reportParseError("unexpected token, expected end of statement");
7794 return false;
7795 }
7796
7797 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007798 } else {
7799 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7800 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007801}
7802
7803/// parseDirectiveModuleFP
7804/// ::= =32
7805/// ::= =xx
7806/// ::= =64
7807bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007808 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007809 MCAsmLexer &Lexer = getLexer();
7810
7811 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007812 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007813 return false;
7814 }
7815 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007816
Daniel Sanders7e527422014-07-10 13:38:23 +00007817 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007818 if (!parseFpABIValue(FpABI, ".module"))
7819 return false;
7820
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007822 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007823 return false;
7824 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007825
Toma Tabacua64e5402015-06-25 12:44:38 +00007826 // Synchronize the abiflags information with the FeatureBits information we
7827 // changed above.
7828 getTargetStreamer().updateABIInfo(*this);
7829
7830 // If printing assembly, use the recently updated abiflags information.
7831 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7832 // emitted at the end).
7833 getTargetStreamer().emitDirectiveModuleFP();
7834
Daniel Sanders7e527422014-07-10 13:38:23 +00007835 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007836 return false;
7837}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007838
Daniel Sanders7e527422014-07-10 13:38:23 +00007839bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007840 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007841 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007842 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007843 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007844
7845 if (Lexer.is(AsmToken::Identifier)) {
7846 StringRef Value = Parser.getTok().getString();
7847 Parser.Lex();
7848
7849 if (Value != "xx") {
7850 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7851 return false;
7852 }
7853
7854 if (!isABI_O32()) {
7855 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7856 return false;
7857 }
7858
Daniel Sanders7e527422014-07-10 13:38:23 +00007859 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007860 if (ModuleLevelOptions) {
7861 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7862 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7863 } else {
7864 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7865 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7866 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007867 return true;
7868 }
7869
7870 if (Lexer.is(AsmToken::Integer)) {
7871 unsigned Value = Parser.getTok().getIntVal();
7872 Parser.Lex();
7873
7874 if (Value != 32 && Value != 64) {
7875 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7876 return false;
7877 }
7878
7879 if (Value == 32) {
7880 if (!isABI_O32()) {
7881 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7882 return false;
7883 }
7884
Daniel Sanders7e527422014-07-10 13:38:23 +00007885 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007886 if (ModuleLevelOptions) {
7887 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7888 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7889 } else {
7890 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7891 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7892 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007893 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007894 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007895 if (ModuleLevelOptions) {
7896 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7897 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7898 } else {
7899 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7900 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7901 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007902 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007903
Daniel Sanders7e527422014-07-10 13:38:23 +00007904 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007905 }
7906
7907 return false;
7908}
7909
Jack Carter0b744b32012-10-04 02:29:46 +00007910bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007911 // This returns false if this function recognizes the directive
7912 // regardless of whether it is successfully handles or reports an
7913 // error. Otherwise it returns true to give the generic parser a
7914 // chance at recognizing it.
7915
Rafael Espindola961d4692014-11-11 05:18:41 +00007916 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007917 StringRef IDVal = DirectiveID.getString();
7918
Nirav Dave996fc132016-05-05 14:15:46 +00007919 if (IDVal == ".cpload") {
7920 parseDirectiveCpLoad(DirectiveID.getLoc());
7921 return false;
7922 }
7923 if (IDVal == ".cprestore") {
7924 parseDirectiveCpRestore(DirectiveID.getLoc());
7925 return false;
7926 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007927 if (IDVal == ".dword") {
7928 parseDataDirective(8, DirectiveID.getLoc());
7929 return false;
7930 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007931 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007932 StringRef SymbolName;
7933
7934 if (Parser.parseIdentifier(SymbolName)) {
7935 reportParseError("expected identifier after .ent");
7936 return false;
7937 }
7938
7939 // There's an undocumented extension that allows an integer to
7940 // follow the name of the procedure which AFAICS is ignored by GAS.
7941 // Example: .ent foo,2
7942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7943 if (getLexer().isNot(AsmToken::Comma)) {
7944 // Even though we accept this undocumented extension for compatibility
7945 // reasons, the additional integer argument does not actually change
7946 // the behaviour of the '.ent' directive, so we would like to discourage
7947 // its use. We do this by not referring to the extended version in
7948 // error messages which are not directly related to its use.
7949 reportParseError("unexpected token, expected end of statement");
7950 return false;
7951 }
7952 Parser.Lex(); // Eat the comma.
7953 const MCExpr *DummyNumber;
7954 int64_t DummyNumberVal;
7955 // If the user was explicitly trying to use the extended version,
7956 // we still give helpful extension-related error messages.
7957 if (Parser.parseExpression(DummyNumber)) {
7958 reportParseError("expected number after comma");
7959 return false;
7960 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007961 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007962 reportParseError("expected an absolute expression after comma");
7963 return false;
7964 }
7965 }
7966
7967 // If this is not the end of the statement, report an error.
7968 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7969 reportParseError("unexpected token, expected end of statement");
7970 return false;
7971 }
7972
Jim Grosbach6f482002015-05-18 18:43:14 +00007973 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007974
7975 getTargetStreamer().emitDirectiveEnt(*Sym);
7976 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007977 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007978 return false;
7979 }
7980
Jack Carter07c818d2013-01-25 01:31:34 +00007981 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007982 StringRef SymbolName;
7983
7984 if (Parser.parseIdentifier(SymbolName)) {
7985 reportParseError("expected identifier after .end");
7986 return false;
7987 }
7988
7989 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7990 reportParseError("unexpected token, expected end of statement");
7991 return false;
7992 }
7993
7994 if (CurrentFn == nullptr) {
7995 reportParseError(".end used without .ent");
7996 return false;
7997 }
7998
7999 if ((SymbolName != CurrentFn->getName())) {
8000 reportParseError(".end symbol does not match .ent symbol");
8001 return false;
8002 }
8003
8004 getTargetStreamer().emitDirectiveEnd(SymbolName);
8005 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008006 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008007 return false;
8008 }
8009
Jack Carter07c818d2013-01-25 01:31:34 +00008010 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008011 // .frame $stack_reg, frame_size_in_bytes, $return_reg
8012 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00008013 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008014 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8015 reportParseError("expected stack register");
8016 return false;
8017 }
8018
8019 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8020 if (!StackRegOpnd.isGPRAsmReg()) {
8021 reportParseError(StackRegOpnd.getStartLoc(),
8022 "expected general purpose register");
8023 return false;
8024 }
8025 unsigned StackReg = StackRegOpnd.getGPR32Reg();
8026
8027 if (Parser.getTok().is(AsmToken::Comma))
8028 Parser.Lex();
8029 else {
8030 reportParseError("unexpected token, expected comma");
8031 return false;
8032 }
8033
8034 // Parse the frame size.
8035 const MCExpr *FrameSize;
8036 int64_t FrameSizeVal;
8037
8038 if (Parser.parseExpression(FrameSize)) {
8039 reportParseError("expected frame size value");
8040 return false;
8041 }
8042
Jim Grosbach13760bd2015-05-30 01:25:56 +00008043 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008044 reportParseError("frame size not an absolute expression");
8045 return false;
8046 }
8047
8048 if (Parser.getTok().is(AsmToken::Comma))
8049 Parser.Lex();
8050 else {
8051 reportParseError("unexpected token, expected comma");
8052 return false;
8053 }
8054
8055 // Parse the return register.
8056 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00008057 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008058 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8059 reportParseError("expected return register");
8060 return false;
8061 }
8062
8063 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8064 if (!ReturnRegOpnd.isGPRAsmReg()) {
8065 reportParseError(ReturnRegOpnd.getStartLoc(),
8066 "expected general purpose register");
8067 return false;
8068 }
8069
8070 // If this is not the end of the statement, report an error.
8071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8072 reportParseError("unexpected token, expected end of statement");
8073 return false;
8074 }
8075
8076 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8077 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008078 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008079 return false;
8080 }
8081
Jack Carter07c818d2013-01-25 01:31:34 +00008082 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008083 parseDirectiveSet();
8084 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008085 }
8086
Daniel Sandersd97a6342014-08-13 10:07:34 +00008087 if (IDVal == ".mask" || IDVal == ".fmask") {
8088 // .mask bitmask, frame_offset
8089 // bitmask: One bit for each register used.
8090 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8091 // first register is expected to be saved.
8092 // Examples:
8093 // .mask 0x80000000, -4
8094 // .fmask 0x80000000, -4
8095 //
Jack Carterbe332172012-09-07 00:48:02 +00008096
Daniel Sandersd97a6342014-08-13 10:07:34 +00008097 // Parse the bitmask
8098 const MCExpr *BitMask;
8099 int64_t BitMaskVal;
8100
8101 if (Parser.parseExpression(BitMask)) {
8102 reportParseError("expected bitmask value");
8103 return false;
8104 }
8105
Jim Grosbach13760bd2015-05-30 01:25:56 +00008106 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008107 reportParseError("bitmask not an absolute expression");
8108 return false;
8109 }
8110
8111 if (Parser.getTok().is(AsmToken::Comma))
8112 Parser.Lex();
8113 else {
8114 reportParseError("unexpected token, expected comma");
8115 return false;
8116 }
8117
8118 // Parse the frame_offset
8119 const MCExpr *FrameOffset;
8120 int64_t FrameOffsetVal;
8121
8122 if (Parser.parseExpression(FrameOffset)) {
8123 reportParseError("expected frame offset value");
8124 return false;
8125 }
8126
Jim Grosbach13760bd2015-05-30 01:25:56 +00008127 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008128 reportParseError("frame offset not an absolute expression");
8129 return false;
8130 }
8131
8132 // If this is not the end of the statement, report an error.
8133 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8134 reportParseError("unexpected token, expected end of statement");
8135 return false;
8136 }
8137
8138 if (IDVal == ".mask")
8139 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8140 else
8141 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008142 return false;
8143 }
8144
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008145 if (IDVal == ".nan")
8146 return parseDirectiveNaN();
8147
Jack Carter07c818d2013-01-25 01:31:34 +00008148 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008149 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008150 return false;
8151 }
8152
Rafael Espindolab59fb732014-03-28 18:50:26 +00008153 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008154 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008155 return false;
8156 }
8157
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008158 if (IDVal == ".dtprelword") {
8159 parseDirectiveDtpRelWord();
8160 return false;
8161 }
8162
8163 if (IDVal == ".dtpreldword") {
8164 parseDirectiveDtpRelDWord();
8165 return false;
8166 }
8167
8168 if (IDVal == ".tprelword") {
8169 parseDirectiveTpRelWord();
8170 return false;
8171 }
8172
8173 if (IDVal == ".tpreldword") {
8174 parseDirectiveTpRelDWord();
8175 return false;
8176 }
8177
Jack Carter07c818d2013-01-25 01:31:34 +00008178 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00008179 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00008180 return false;
8181 }
8182
Scott Egertond1aeb052016-02-15 16:11:51 +00008183 if (IDVal == ".hword") {
8184 parseDataDirective(2, DirectiveID.getLoc());
8185 return false;
8186 }
8187
Nirav Dave996fc132016-05-05 14:15:46 +00008188 if (IDVal == ".option") {
8189 parseDirectiveOption();
8190 return false;
8191 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008192
8193 if (IDVal == ".abicalls") {
8194 getTargetStreamer().emitDirectiveAbiCalls();
8195 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00008196 Error(Parser.getTok().getLoc(),
8197 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008198 }
8199 return false;
8200 }
8201
Nirav Dave996fc132016-05-05 14:15:46 +00008202 if (IDVal == ".cpsetup") {
8203 parseDirectiveCPSetup();
8204 return false;
8205 }
8206 if (IDVal == ".cpreturn") {
8207 parseDirectiveCPReturn();
8208 return false;
8209 }
8210 if (IDVal == ".module") {
8211 parseDirectiveModule();
8212 return false;
8213 }
8214 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8215 parseInternalDirectiveReallowModule();
8216 return false;
8217 }
8218 if (IDVal == ".insn") {
8219 parseInsnDirective();
8220 return false;
8221 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008222 if (IDVal == ".rdata") {
8223 parseRSectionDirective(".rodata");
8224 return false;
8225 }
Nirav Dave996fc132016-05-05 14:15:46 +00008226 if (IDVal == ".sbss") {
8227 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8228 return false;
8229 }
8230 if (IDVal == ".sdata") {
8231 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8232 return false;
8233 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008234
Rafael Espindola870c4e92012-01-11 03:56:41 +00008235 return true;
8236}
8237
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008238bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8239 // If this is not the end of the statement, report an error.
8240 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8241 reportParseError("unexpected token, expected end of statement");
8242 return false;
8243 }
8244
8245 getTargetStreamer().reallowModuleDirective();
8246
8247 getParser().Lex(); // Eat EndOfStatement token.
8248 return false;
8249}
8250
Rafael Espindola870c4e92012-01-11 03:56:41 +00008251extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008252 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8253 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8254 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8255 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008256}
Jack Carterb4dbc172012-09-05 23:34:03 +00008257
8258#define GET_REGISTER_MATCHER
8259#define GET_MATCHER_IMPLEMENTATION
8260#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008261
8262bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8263 // Find the appropriate table for this asm variant.
8264 const MatchEntry *Start, *End;
8265 switch (VariantID) {
8266 default: llvm_unreachable("invalid variant!");
8267 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8268 }
8269 // Search the table.
8270 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8271 return MnemonicRange.first != MnemonicRange.second;
8272}