blob: 942a3a8a589f27ad33911e0c98feef35b195e9d2 [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 {
Simon Atanasyan478220f2018-05-24 07:36:00 +00001359 if (isConstantImm() &&
1360 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001361 return true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00001362 // Operand can also be a symbol or symbol plus
1363 // offset in case of relocations.
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001364 if (Kind != k_Immediate)
1365 return false;
1366 MCValue Res;
1367 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1368 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001369 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001370
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001371 bool isRegList16() const {
1372 if (!isRegList())
1373 return false;
1374
1375 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001376 if (Size < 2 || Size > 5)
1377 return false;
1378
1379 unsigned R0 = RegList.List->front();
1380 unsigned R1 = RegList.List->back();
1381 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1382 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001383 return false;
1384
1385 int PrevReg = *RegList.List->begin();
1386 for (int i = 1; i < Size - 1; i++) {
1387 int Reg = (*(RegList.List))[i];
1388 if ( Reg != PrevReg + 1)
1389 return false;
1390 PrevReg = Reg;
1391 }
1392
1393 return true;
1394 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001395
Vladimir Medic2b953d02013-10-01 09:48:56 +00001396 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001397
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001398 bool isLSAImm() const {
1399 if (!isConstantImm())
1400 return false;
1401 int64_t Val = getConstantImm();
1402 return 1 <= Val && Val <= 4;
1403 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001404
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001405 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001406
Zoran Jovanovic41688672015-02-10 16:36:20 +00001407 bool isMovePRegPair() const {
1408 if (Kind != k_RegList || RegList.List->size() != 2)
1409 return false;
1410
1411 unsigned R0 = RegList.List->front();
1412 unsigned R1 = RegList.List->back();
1413
1414 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1415 (R0 == Mips::A1 && R1 == Mips::A3) ||
1416 (R0 == Mips::A2 && R1 == Mips::A3) ||
1417 (R0 == Mips::A0 && R1 == Mips::S5) ||
1418 (R0 == Mips::A0 && R1 == Mips::S6) ||
1419 (R0 == Mips::A0 && R1 == Mips::A1) ||
1420 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001421 (R0 == Mips::A0 && R1 == Mips::A3) ||
1422 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1423 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1424 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1425 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1426 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1427 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1428 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1429 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001430 return true;
1431
1432 return false;
1433 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001434
1435 StringRef getToken() const {
1436 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001437 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001438 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001439
Zlatko Buljanba553a62016-05-09 08:07:28 +00001440 bool isRegPair() const {
1441 return Kind == k_RegPair && RegIdx.Index <= 30;
1442 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001443
Craig Topper56c590a2014-04-29 07:58:02 +00001444 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001445 // As a special case until we sort out the definition of div/divu, accept
1446 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001447 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1448 RegIdx.Kind & RegKind_GPR)
1449 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001450
Daniel Sanders976d9382016-07-05 13:38:40 +00001451 llvm_unreachable("Invalid access!");
1452 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001453 }
1454
Jack Carterb4dbc172012-09-05 23:34:03 +00001455 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001456 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001457 return Imm.Val;
1458 }
1459
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001460 int64_t getConstantImm() const {
1461 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001462 int64_t Value = 0;
1463 (void)Val->evaluateAsAbsolute(Value);
1464 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001465 }
1466
1467 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001468 assert((Kind == k_Memory) && "Invalid access!");
1469 return Mem.Base;
1470 }
1471
1472 const MCExpr *getMemOff() const {
1473 assert((Kind == k_Memory) && "Invalid access!");
1474 return Mem.Off;
1475 }
1476
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001477 int64_t getConstantMemOff() const {
1478 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1479 }
1480
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001481 const SmallVectorImpl<unsigned> &getRegList() const {
1482 assert((Kind == k_RegList) && "Invalid access!");
1483 return *(RegList.List);
1484 }
1485
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001486 unsigned getRegPair() const {
1487 assert((Kind == k_RegPair) && "Invalid access!");
1488 return RegIdx.Index;
1489 }
1490
David Blaikie960ea3f2014-06-08 16:18:35 +00001491 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1492 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001493 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001494 Op->Tok.Data = Str.data();
1495 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001496 Op->StartLoc = S;
1497 Op->EndLoc = S;
1498 return Op;
1499 }
1500
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001501 /// Create a numeric register (e.g. $1). The exact register remains
1502 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001503 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001504 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1505 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001506 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001507 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001508 }
1509
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001510 /// Create a register that is definitely a GPR.
1511 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001512 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001513 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1514 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1515 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001516 }
1517
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001518 /// Create a register that is definitely a FGR.
1519 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001520 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001521 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1522 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1523 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001524 }
1525
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001526 /// Create a register that is definitely a HWReg.
1527 /// This is typically only used for named registers such as $hwr_cpunum.
1528 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001529 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001530 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001531 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001532 }
1533
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001534 /// Create a register that is definitely an FCC.
1535 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001536 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001537 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1538 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1539 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001540 }
1541
1542 /// Create a register that is definitely an ACC.
1543 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001544 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001545 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1546 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1547 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001548 }
1549
1550 /// Create a register that is definitely an MSA128.
1551 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001552 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001553 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1554 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1555 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001556 }
1557
1558 /// Create a register that is definitely an MSACtrl.
1559 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001560 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001561 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1562 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1563 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001564 }
1565
David Blaikie960ea3f2014-06-08 16:18:35 +00001566 static std::unique_ptr<MipsOperand>
1567 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001568 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001569 Op->Imm.Val = Val;
1570 Op->StartLoc = S;
1571 Op->EndLoc = E;
1572 return Op;
1573 }
1574
David Blaikie960ea3f2014-06-08 16:18:35 +00001575 static std::unique_ptr<MipsOperand>
1576 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1577 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001578 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001579 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001580 Op->Mem.Off = Off;
1581 Op->StartLoc = S;
1582 Op->EndLoc = E;
1583 return Op;
1584 }
1585
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001586 static std::unique_ptr<MipsOperand>
1587 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1588 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001589 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001590
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001591 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001592 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001593 Op->StartLoc = StartLoc;
1594 Op->EndLoc = EndLoc;
1595 return Op;
1596 }
1597
Daniel Sandersd044e492016-05-09 13:10:57 +00001598 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1599 SMLoc S, SMLoc E,
1600 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001601 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001602 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001603 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1604 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001605 Op->StartLoc = S;
1606 Op->EndLoc = E;
1607 return Op;
1608 }
1609
Simon Dardis509da1a2017-02-13 16:06:48 +00001610 bool isGPRZeroAsmReg() const {
1611 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1612 }
1613
1614 bool isGPRNonZeroAsmReg() const {
1615 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1616 RegIdx.Index <= 31;
1617 }
1618
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001619 bool isGPRAsmReg() const {
1620 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001622
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001623 bool isMM16AsmReg() const {
1624 if (!(isRegIdx() && RegIdx.Kind))
1625 return false;
1626 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1627 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001628
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001629 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001630 bool isMM16AsmRegZero() const {
1631 if (!(isRegIdx() && RegIdx.Kind))
1632 return false;
1633 return (RegIdx.Index == 0 ||
1634 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1635 RegIdx.Index == 17);
1636 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001637
Zoran Jovanovic41688672015-02-10 16:36:20 +00001638 bool isMM16AsmRegMoveP() const {
1639 if (!(isRegIdx() && RegIdx.Kind))
1640 return false;
1641 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1642 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1643 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001644
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001645 bool isFGRAsmReg() const {
1646 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1647 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001648 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001649
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001650 bool isStrictlyFGRAsmReg() const {
1651 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1652 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1653 }
1654
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001655 bool isHWRegsAsmReg() const {
1656 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001657 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001658
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001659 bool isCCRAsmReg() const {
1660 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001661 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001662
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001663 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001664 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1665 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001666 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001667 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001668
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 bool isACCAsmReg() const {
1670 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001671 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001672
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001673 bool isCOP0AsmReg() const {
1674 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1675 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001676
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001677 bool isCOP2AsmReg() const {
1678 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001679 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001680
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001681 bool isCOP3AsmReg() const {
1682 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1683 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001684
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001685 bool isMSA128AsmReg() const {
1686 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001687 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001688
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001689 bool isMSACtrlAsmReg() const {
1690 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001691 }
1692
Jack Carterb4dbc172012-09-05 23:34:03 +00001693 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001694 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001695 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001696 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001697
Craig Topper56c590a2014-04-29 07:58:02 +00001698 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001699 switch (Kind) {
1700 case k_Immediate:
1701 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001702 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001703 OS << ">";
1704 break;
1705 case k_Memory:
1706 OS << "Mem<";
1707 Mem.Base->print(OS);
1708 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001709 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001710 OS << ">";
1711 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001712 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001713 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1714 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001715 break;
1716 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001717 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001718 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001719 case k_RegList:
1720 OS << "RegList< ";
1721 for (auto Reg : (*RegList.List))
1722 OS << Reg << " ";
1723 OS << ">";
1724 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001725 case k_RegPair:
1726 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1727 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001728 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001729 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001730
1731 bool isValidForTie(const MipsOperand &Other) const {
1732 if (Kind != Other.Kind)
1733 return false;
1734
1735 switch (Kind) {
1736 default:
1737 llvm_unreachable("Unexpected kind");
1738 return false;
1739 case k_RegisterIndex: {
1740 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1741 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1742 return Token == OtherToken;
1743 }
1744 }
1745 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001746}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001747
1748} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001749
Jack Carter9e65aa32013-03-22 00:05:30 +00001750namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001751
Jack Carter9e65aa32013-03-22 00:05:30 +00001752extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001753
1754} // end namespace llvm
1755
Jack Carter9e65aa32013-03-22 00:05:30 +00001756static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1757 return MipsInsts[Opcode];
1758}
1759
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001760static bool hasShortDelaySlot(unsigned Opcode) {
1761 switch (Opcode) {
1762 case Mips::JALS_MM:
1763 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001764 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001765 case Mips::BGEZALS_MM:
1766 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001767 return true;
1768 default:
1769 return false;
1770 }
1771}
1772
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001773static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1774 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1775 return &SRExpr->getSymbol();
1776 }
1777
1778 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1779 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1780 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1781
1782 if (LHSSym)
1783 return LHSSym;
1784
1785 if (RHSSym)
1786 return RHSSym;
1787
1788 return nullptr;
1789 }
1790
1791 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1792 return getSingleMCSymbol(UExpr->getSubExpr());
1793
1794 return nullptr;
1795}
1796
1797static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1798 if (isa<MCSymbolRefExpr>(Expr))
1799 return 1;
1800
1801 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1802 return countMCSymbolRefExpr(BExpr->getLHS()) +
1803 countMCSymbolRefExpr(BExpr->getRHS());
1804
1805 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1806 return countMCSymbolRefExpr(UExpr->getSubExpr());
1807
1808 return 0;
1809}
1810
Jack Carter9e65aa32013-03-22 00:05:30 +00001811bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001812 MCStreamer &Out,
1813 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001814 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001815 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001816 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001817
Jack Carter9e65aa32013-03-22 00:05:30 +00001818 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001819
1820 if (MCID.isBranch() || MCID.isCall()) {
1821 const unsigned Opcode = Inst.getOpcode();
1822 MCOperand Offset;
1823
1824 switch (Opcode) {
1825 default:
1826 break;
Kai Nackee0245392015-01-27 19:11:28 +00001827 case Mips::BBIT0:
1828 case Mips::BBIT032:
1829 case Mips::BBIT1:
1830 case Mips::BBIT132:
1831 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001832 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001833
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001834 case Mips::BEQ:
1835 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001836 case Mips::BEQ_MM:
1837 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001838 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001839 Offset = Inst.getOperand(2);
1840 if (!Offset.isImm())
1841 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001842 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001843 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001844 if (OffsetToAlignment(Offset.getImm(),
1845 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001846 return Error(IDLoc, "branch to misaligned address");
1847 break;
1848 case Mips::BGEZ:
1849 case Mips::BGTZ:
1850 case Mips::BLEZ:
1851 case Mips::BLTZ:
1852 case Mips::BGEZAL:
1853 case Mips::BLTZAL:
1854 case Mips::BC1F:
1855 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001856 case Mips::BGEZ_MM:
1857 case Mips::BGTZ_MM:
1858 case Mips::BLEZ_MM:
1859 case Mips::BLTZ_MM:
1860 case Mips::BGEZAL_MM:
1861 case Mips::BLTZAL_MM:
1862 case Mips::BC1F_MM:
1863 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001864 case Mips::BC1EQZC_MMR6:
1865 case Mips::BC1NEZC_MMR6:
1866 case Mips::BC2EQZC_MMR6:
1867 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001868 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001869 Offset = Inst.getOperand(1);
1870 if (!Offset.isImm())
1871 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001872 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001873 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001874 if (OffsetToAlignment(Offset.getImm(),
1875 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001876 return Error(IDLoc, "branch to misaligned address");
1877 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001878 case Mips::BGEC: case Mips::BGEC_MMR6:
1879 case Mips::BLTC: case Mips::BLTC_MMR6:
1880 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1881 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1882 case Mips::BEQC: case Mips::BEQC_MMR6:
1883 case Mips::BNEC: case Mips::BNEC_MMR6:
1884 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1885 Offset = Inst.getOperand(2);
1886 if (!Offset.isImm())
1887 break; // We'll deal with this situation later on when applying fixups.
1888 if (!isIntN(18, Offset.getImm()))
1889 return Error(IDLoc, "branch target out of range");
1890 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1891 return Error(IDLoc, "branch to misaligned address");
1892 break;
1893 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1894 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1895 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1896 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1897 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1898 Offset = Inst.getOperand(1);
1899 if (!Offset.isImm())
1900 break; // We'll deal with this situation later on when applying fixups.
1901 if (!isIntN(18, Offset.getImm()))
1902 return Error(IDLoc, "branch target out of range");
1903 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1904 return Error(IDLoc, "branch to misaligned address");
1905 break;
1906 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1907 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1908 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1909 Offset = Inst.getOperand(1);
1910 if (!Offset.isImm())
1911 break; // We'll deal with this situation later on when applying fixups.
1912 if (!isIntN(23, Offset.getImm()))
1913 return Error(IDLoc, "branch target out of range");
1914 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1915 return Error(IDLoc, "branch to misaligned address");
1916 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001917 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001918 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001919 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001920 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001921 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1922 Offset = Inst.getOperand(1);
1923 if (!Offset.isImm())
1924 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001925 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001926 return Error(IDLoc, "branch target out of range");
1927 if (OffsetToAlignment(Offset.getImm(), 2LL))
1928 return Error(IDLoc, "branch to misaligned address");
1929 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001930 }
1931 }
1932
Daniel Sandersa84989a2014-06-16 13:25:35 +00001933 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1934 // We still accept it but it is a normal nop.
1935 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1936 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1937 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1938 "nop instruction");
1939 }
1940
Kai Nackee0245392015-01-27 19:11:28 +00001941 if (hasCnMips()) {
1942 const unsigned Opcode = Inst.getOpcode();
1943 MCOperand Opnd;
1944 int Imm;
1945
1946 switch (Opcode) {
1947 default:
1948 break;
1949
1950 case Mips::BBIT0:
1951 case Mips::BBIT032:
1952 case Mips::BBIT1:
1953 case Mips::BBIT132:
1954 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1955 // The offset is handled above
1956 Opnd = Inst.getOperand(1);
1957 if (!Opnd.isImm())
1958 return Error(IDLoc, "expected immediate operand kind");
1959 Imm = Opnd.getImm();
1960 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1961 Opcode == Mips::BBIT1 ? 63 : 31))
1962 return Error(IDLoc, "immediate operand value out of range");
1963 if (Imm > 31) {
1964 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1965 : Mips::BBIT132);
1966 Inst.getOperand(1).setImm(Imm - 32);
1967 }
1968 break;
1969
Kai Nackee0245392015-01-27 19:11:28 +00001970 case Mips::SEQi:
1971 case Mips::SNEi:
1972 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1973 Opnd = Inst.getOperand(2);
1974 if (!Opnd.isImm())
1975 return Error(IDLoc, "expected immediate operand kind");
1976 Imm = Opnd.getImm();
1977 if (!isInt<10>(Imm))
1978 return Error(IDLoc, "immediate operand value out of range");
1979 break;
1980 }
1981 }
1982
Simon Dardis509da1a2017-02-13 16:06:48 +00001983 // Warn on division by zero. We're checking here as all instructions get
1984 // processed here, not just the macros that need expansion.
1985 //
1986 // The MIPS backend models most of the divison instructions and macros as
1987 // three operand instructions. The pre-R6 divide instructions however have
1988 // two operands and explicitly define HI/LO as part of the instruction,
1989 // not in the operands.
1990 unsigned FirstOp = 1;
1991 unsigned SecondOp = 2;
1992 switch (Inst.getOpcode()) {
1993 default:
1994 break;
1995 case Mips::SDivIMacro:
1996 case Mips::UDivIMacro:
1997 case Mips::DSDivIMacro:
1998 case Mips::DUDivIMacro:
1999 if (Inst.getOperand(2).getImm() == 0) {
2000 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
2001 Inst.getOperand(1).getReg() == Mips::ZERO_64)
2002 Warning(IDLoc, "dividing zero by zero");
2003 else
2004 Warning(IDLoc, "division by zero");
2005 }
2006 break;
2007 case Mips::DSDIV:
2008 case Mips::SDIV:
2009 case Mips::UDIV:
2010 case Mips::DUDIV:
2011 case Mips::UDIV_MM:
2012 case Mips::SDIV_MM:
2013 FirstOp = 0;
2014 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00002015 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00002016 case Mips::SDivMacro:
2017 case Mips::DSDivMacro:
2018 case Mips::UDivMacro:
2019 case Mips::DUDivMacro:
2020 case Mips::DIV:
2021 case Mips::DIVU:
2022 case Mips::DDIV:
2023 case Mips::DDIVU:
2024 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002025 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002026 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
2027 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
2028 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
2029 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
2030 Warning(IDLoc, "dividing zero by zero");
2031 else
2032 Warning(IDLoc, "division by zero");
2033 }
2034 break;
2035 }
2036
Simon Atanasyan50485142016-12-12 17:40:26 +00002037 // For PIC code convert unconditional jump to unconditional branch.
2038 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2039 inPicMode()) {
2040 MCInst BInst;
2041 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2042 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2043 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2044 BInst.addOperand(Inst.getOperand(0));
2045 Inst = BInst;
2046 }
2047
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002048 // This expansion is not in a function called by tryExpandInstruction()
2049 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002050 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2051 inPicMode()) {
2052 warnIfNoMacro(IDLoc);
2053
2054 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2055
2056 // We can do this expansion if there's only 1 symbol in the argument
2057 // expression.
2058 if (countMCSymbolRefExpr(JalExpr) > 1)
2059 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2060
2061 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002062 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002063 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2064
2065 // FIXME: Add support for label+offset operands (currently causes an error).
2066 // FIXME: Add support for forward-declared local symbols.
2067 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002068 if (JalSym->isInSection() || JalSym->isTemporary() ||
Simon Atanasyan478220f2018-05-24 07:36:00 +00002069 (JalSym->isELF() &&
2070 cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002071 if (isABI_O32()) {
2072 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002073 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002074 // R_(MICRO)MIPS_GOT16 label
2075 // addiu $25, $25, 0
2076 // R_(MICRO)MIPS_LO16 label
2077 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002078 const MCExpr *Got16RelocExpr =
2079 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2080 const MCExpr *Lo16RelocExpr =
2081 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002082
Daniel Sandersa736b372016-04-29 13:33:12 +00002083 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2084 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2085 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2086 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002087 } else if (isABI_N32() || isABI_N64()) {
2088 // If it's a local symbol and the N32/N64 ABIs are being used,
2089 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002090 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002091 // R_(MICRO)MIPS_GOT_DISP label
2092 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002093 const MCExpr *GotDispRelocExpr =
2094 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002095
Daniel Sandersa736b372016-04-29 13:33:12 +00002096 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2097 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2098 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002099 }
2100 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002101 // If it's an external/weak symbol, we expand to:
2102 // lw/ld $25, 0($gp)
2103 // R_(MICRO)MIPS_CALL16 label
2104 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002105 const MCExpr *Call16RelocExpr =
2106 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002107
Daniel Sandersa736b372016-04-29 13:33:12 +00002108 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2109 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002110 }
2111
2112 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002113 if (IsCpRestoreSet && inMicroMipsMode())
2114 JalrInst.setOpcode(Mips::JALRS_MM);
2115 else
2116 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002117 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2118 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2119
2120 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2121 // This relocation is supposed to be an optimization hint for the linker
2122 // and is not necessary for correctness.
2123
2124 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002125 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002126 }
2127
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002128 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2129 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002130 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002131 // reference or immediate we may have to expand instructions.
2132 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002133 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002134 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2135 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002136 MCOperand &Op = Inst.getOperand(i);
2137 if (Op.isImm()) {
2138 int MemOffset = Op.getImm();
2139 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002140 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002141 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002142 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002143 }
2144 } else if (Op.isExpr()) {
2145 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002146 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002147 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002148 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002149 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002150 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002151 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002152 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002153 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002154 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002155 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002156 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002157 }
2158 }
2159 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002160 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002161 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002162
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002163 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002164 if (MCID.mayLoad()) {
2165 // Try to create 16-bit GP relative load instruction.
2166 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2167 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2168 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2169 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2170 MCOperand &Op = Inst.getOperand(i);
2171 if (Op.isImm()) {
2172 int MemOffset = Op.getImm();
2173 MCOperand &DstReg = Inst.getOperand(0);
2174 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002175 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002176 getContext().getRegisterInfo()->getRegClass(
2177 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002178 (BaseReg.getReg() == Mips::GP ||
2179 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002180
Daniel Sandersa736b372016-04-29 13:33:12 +00002181 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2182 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002183 return false;
2184 }
2185 }
2186 }
2187 } // for
2188 } // if load
2189
2190 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2191
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002192 MCOperand Opnd;
2193 int Imm;
2194
2195 switch (Inst.getOpcode()) {
2196 default:
2197 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002198 case Mips::ADDIUSP_MM:
2199 Opnd = Inst.getOperand(0);
2200 if (!Opnd.isImm())
2201 return Error(IDLoc, "expected immediate operand kind");
2202 Imm = Opnd.getImm();
2203 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2204 Imm % 4 != 0)
2205 return Error(IDLoc, "immediate operand value out of range");
2206 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002207 case Mips::SLL16_MM:
2208 case Mips::SRL16_MM:
2209 Opnd = Inst.getOperand(2);
2210 if (!Opnd.isImm())
2211 return Error(IDLoc, "expected immediate operand kind");
2212 Imm = Opnd.getImm();
2213 if (Imm < 1 || Imm > 8)
2214 return Error(IDLoc, "immediate operand value out of range");
2215 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002216 case Mips::LI16_MM:
2217 Opnd = Inst.getOperand(1);
2218 if (!Opnd.isImm())
2219 return Error(IDLoc, "expected immediate operand kind");
2220 Imm = Opnd.getImm();
2221 if (Imm < -1 || Imm > 126)
2222 return Error(IDLoc, "immediate operand value out of range");
2223 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002224 case Mips::ADDIUR2_MM:
2225 Opnd = Inst.getOperand(2);
2226 if (!Opnd.isImm())
2227 return Error(IDLoc, "expected immediate operand kind");
2228 Imm = Opnd.getImm();
2229 if (!(Imm == 1 || Imm == -1 ||
2230 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2231 return Error(IDLoc, "immediate operand value out of range");
2232 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002233 case Mips::ANDI16_MM:
2234 Opnd = Inst.getOperand(2);
2235 if (!Opnd.isImm())
2236 return Error(IDLoc, "expected immediate operand kind");
2237 Imm = Opnd.getImm();
2238 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2239 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2240 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2241 return Error(IDLoc, "immediate operand value out of range");
2242 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002243 case Mips::LBU16_MM:
2244 Opnd = Inst.getOperand(2);
2245 if (!Opnd.isImm())
2246 return Error(IDLoc, "expected immediate operand kind");
2247 Imm = Opnd.getImm();
2248 if (Imm < -1 || Imm > 14)
2249 return Error(IDLoc, "immediate operand value out of range");
2250 break;
2251 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002252 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002253 Opnd = Inst.getOperand(2);
2254 if (!Opnd.isImm())
2255 return Error(IDLoc, "expected immediate operand kind");
2256 Imm = Opnd.getImm();
2257 if (Imm < 0 || Imm > 15)
2258 return Error(IDLoc, "immediate operand value out of range");
2259 break;
2260 case Mips::LHU16_MM:
2261 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002262 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002263 Opnd = Inst.getOperand(2);
2264 if (!Opnd.isImm())
2265 return Error(IDLoc, "expected immediate operand kind");
2266 Imm = Opnd.getImm();
2267 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2268 return Error(IDLoc, "immediate operand value out of range");
2269 break;
2270 case Mips::LW16_MM:
2271 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002272 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002273 Opnd = Inst.getOperand(2);
2274 if (!Opnd.isImm())
2275 return Error(IDLoc, "expected immediate operand kind");
2276 Imm = Opnd.getImm();
2277 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2278 return Error(IDLoc, "immediate operand value out of range");
2279 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002280 case Mips::ADDIUPC_MM:
2281 MCOperand Opnd = Inst.getOperand(1);
2282 if (!Opnd.isImm())
2283 return Error(IDLoc, "expected immediate operand kind");
2284 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002285 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002286 return Error(IDLoc, "immediate operand value out of range");
2287 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002288 }
2289 }
2290
Daniel Sandersd8c07762016-04-18 12:35:36 +00002291 bool FillDelaySlot =
2292 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2293 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002294 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002295
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002296 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002297 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002298 switch (ExpandResult) {
2299 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002300 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002301 break;
2302 case MER_Success:
2303 break;
2304 case MER_Fail:
2305 return true;
2306 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002307
Daniel Sanderscda908a2016-05-16 09:10:13 +00002308 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2309 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002310 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002311 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002312 TOut.updateABIInfo(*this);
2313 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002314
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002315 // If this instruction has a delay slot and .set reorder is active,
2316 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002317 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002318 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2319 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002320 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002321
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002322 if ((Inst.getOpcode() == Mips::JalOneReg ||
2323 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2324 isPicAndNotNxxAbi()) {
2325 if (IsCpRestoreSet) {
2326 // We need a NOP between the JALR and the LW:
2327 // If .set reorder has been used, we've already emitted a NOP.
2328 // If .set noreorder has been used, we need to emit a NOP at this point.
2329 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002330 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2331 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002332
2333 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002334 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002335 } else
2336 Warning(IDLoc, "no .cprestore used in PIC mode");
2337 }
2338
Jack Carter9e65aa32013-03-22 00:05:30 +00002339 return false;
2340}
2341
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002342MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002343MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2344 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002345 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002346 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002347 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002348 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002349 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002350 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002351 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002352 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002353 case Mips::LoadAddrImm64:
2354 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2355 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2356 "expected immediate operand kind");
2357
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002358 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2359 Inst.getOperand(1),
2360 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002361 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002362 ? MER_Fail
2363 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002364 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002365 case Mips::LoadAddrReg64:
2366 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2367 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2368 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2369 "expected immediate operand kind");
2370
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002371 return expandLoadAddress(Inst.getOperand(0).getReg(),
2372 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2373 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002374 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002375 ? MER_Fail
2376 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002377 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002378 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002379 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2380 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002381 case Mips::SWM_MM:
2382 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002383 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2384 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002385 case Mips::JalOneReg:
2386 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002387 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002388 case Mips::BneImm:
2389 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002390 case Mips::BEQLImmMacro:
2391 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002392 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002393 case Mips::BLT:
2394 case Mips::BLE:
2395 case Mips::BGE:
2396 case Mips::BGT:
2397 case Mips::BLTU:
2398 case Mips::BLEU:
2399 case Mips::BGEU:
2400 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002401 case Mips::BLTL:
2402 case Mips::BLEL:
2403 case Mips::BGEL:
2404 case Mips::BGTL:
2405 case Mips::BLTUL:
2406 case Mips::BLEUL:
2407 case Mips::BGEUL:
2408 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002409 case Mips::BLTImmMacro:
2410 case Mips::BLEImmMacro:
2411 case Mips::BGEImmMacro:
2412 case Mips::BGTImmMacro:
2413 case Mips::BLTUImmMacro:
2414 case Mips::BLEUImmMacro:
2415 case Mips::BGEUImmMacro:
2416 case Mips::BGTUImmMacro:
2417 case Mips::BLTLImmMacro:
2418 case Mips::BLELImmMacro:
2419 case Mips::BGELImmMacro:
2420 case Mips::BGTLImmMacro:
2421 case Mips::BLTULImmMacro:
2422 case Mips::BLEULImmMacro:
2423 case Mips::BGEULImmMacro:
2424 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002425 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002426 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002427 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002428 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2429 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002430 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002431 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002432 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2433 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002434 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002435 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002436 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2437 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002438 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002439 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002440 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2441 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002442 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002443 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2444 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002445 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002446 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002447 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002448 case Mips::PseudoTRUNC_W_D:
2449 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2450 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002451
2452 case Mips::LoadImmSingleGPR:
2453 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2454 ? MER_Fail
2455 : MER_Success;
2456 case Mips::LoadImmSingleFGR:
2457 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2458 ? MER_Fail
2459 : MER_Success;
2460 case Mips::LoadImmDoubleGPR:
2461 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2462 ? MER_Fail
2463 : MER_Success;
2464 case Mips::LoadImmDoubleFGR:
2465 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2466 ? MER_Fail
2467 : MER_Success;
2468 case Mips::LoadImmDoubleFGR_32:
2469 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2470 ? MER_Fail
2471 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002472 case Mips::Ulh:
2473 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2474 case Mips::Ulhu:
2475 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002476 case Mips::Ush:
2477 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002478 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002479 case Mips::Usw:
2480 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002481 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002482 case Mips::NORImm64:
2483 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2484 case Mips::SLTImm64:
2485 if (isInt<16>(Inst.getOperand(2).getImm())) {
2486 Inst.setOpcode(Mips::SLTi64);
2487 return MER_NotAMacro;
2488 }
2489 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2490 case Mips::SLTUImm64:
2491 if (isInt<16>(Inst.getOperand(2).getImm())) {
2492 Inst.setOpcode(Mips::SLTiu64);
2493 return MER_NotAMacro;
2494 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002495 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002496 case Mips::ADDi: case Mips::ADDi_MM:
2497 case Mips::ADDiu: case Mips::ADDiu_MM:
2498 case Mips::SLTi: case Mips::SLTi_MM:
2499 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002500 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2501 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2502 int64_t ImmValue = Inst.getOperand(2).getImm();
2503 if (isInt<16>(ImmValue))
2504 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002505 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2506 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002507 }
2508 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002509 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2510 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2511 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002512 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2513 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2514 int64_t ImmValue = Inst.getOperand(2).getImm();
2515 if (isUInt<16>(ImmValue))
2516 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002517 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2518 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002519 }
2520 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002521 case Mips::ROL:
2522 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002523 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002524 case Mips::ROLImm:
2525 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002526 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002527 case Mips::DROL:
2528 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002529 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002530 case Mips::DROLImm:
2531 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002532 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002533 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002534 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002535 case Mips::MULImmMacro:
2536 case Mips::DMULImmMacro:
2537 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2538 case Mips::MULOMacro:
2539 case Mips::DMULOMacro:
2540 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2541 case Mips::MULOUMacro:
2542 case Mips::DMULOUMacro:
2543 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2544 case Mips::DMULMacro:
2545 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002546 case Mips::LDMacro:
2547 case Mips::SDMacro:
2548 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2549 Inst.getOpcode() == Mips::LDMacro)
2550 ? MER_Fail
2551 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002552 case Mips::SEQMacro:
2553 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2554 case Mips::SEQIMacro:
2555 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002556 case Mips::MFTC0: case Mips::MTTC0:
2557 case Mips::MFTGPR: case Mips::MTTGPR:
2558 case Mips::MFTLO: case Mips::MTTLO:
2559 case Mips::MFTHI: case Mips::MTTHI:
2560 case Mips::MFTACX: case Mips::MTTACX:
2561 case Mips::MFTDSP: case Mips::MTTDSP:
2562 case Mips::MFTC1: case Mips::MTTC1:
2563 case Mips::MFTHC1: case Mips::MTTHC1:
2564 case Mips::CFTC1: case Mips::CTTC1:
2565 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002566 }
Jack Carter30a59822012-10-04 04:03:53 +00002567}
Jack Carter92995f12012-10-06 00:53:28 +00002568
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002569bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002570 MCStreamer &Out,
2571 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002572 MipsTargetStreamer &TOut = getTargetStreamer();
2573
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002574 // Create a JALR instruction which is going to replace the pseudo-JAL.
2575 MCInst JalrInst;
2576 JalrInst.setLoc(IDLoc);
2577 const MCOperand FirstRegOp = Inst.getOperand(0);
2578 const unsigned Opcode = Inst.getOpcode();
2579
2580 if (Opcode == Mips::JalOneReg) {
2581 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002582 if (IsCpRestoreSet && inMicroMipsMode()) {
2583 JalrInst.setOpcode(Mips::JALRS16_MM);
2584 JalrInst.addOperand(FirstRegOp);
2585 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002586 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002587 JalrInst.addOperand(FirstRegOp);
2588 } else {
2589 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002590 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002591 JalrInst.addOperand(FirstRegOp);
2592 }
2593 } else if (Opcode == Mips::JalTwoReg) {
2594 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002595 if (IsCpRestoreSet && inMicroMipsMode())
2596 JalrInst.setOpcode(Mips::JALRS_MM);
2597 else
2598 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002599 JalrInst.addOperand(FirstRegOp);
2600 const MCOperand SecondRegOp = Inst.getOperand(1);
2601 JalrInst.addOperand(SecondRegOp);
2602 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002603 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002604
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002605 // If .set reorder is active and branch instruction has a delay slot,
2606 // emit a NOP after it.
2607 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002608 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2609 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2610 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002611
2612 return false;
2613}
2614
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002615/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002616template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002617 unsigned BitNum = findFirstSet(x);
2618
2619 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2620}
2621
2622/// Load (or add) an immediate into a register.
2623///
2624/// @param ImmValue The immediate to load.
2625/// @param DstReg The register that will hold the immediate.
2626/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2627/// for a simple initialization.
2628/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2629/// @param IsAddress True if the immediate represents an address. False if it
2630/// is an integer.
2631/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002632bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002633 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002634 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2635 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002636 MipsTargetStreamer &TOut = getTargetStreamer();
2637
Toma Tabacu00e98672015-05-01 12:19:27 +00002638 if (!Is32BitImm && !isGP64bit()) {
2639 Error(IDLoc, "instruction requires a 64-bit architecture");
2640 return true;
2641 }
2642
Daniel Sanders03f9c012015-07-14 12:24:22 +00002643 if (Is32BitImm) {
2644 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2645 // Sign extend up to 64-bit so that the predicates match the hardware
2646 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2647 // true.
2648 ImmValue = SignExtend64<32>(ImmValue);
2649 } else {
2650 Error(IDLoc, "instruction requires a 32-bit immediate");
2651 return true;
2652 }
2653 }
2654
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002655 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2656 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2657
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002658 bool UseSrcReg = false;
2659 if (SrcReg != Mips::NoRegister)
2660 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002661
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002662 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002663 if (UseSrcReg &&
2664 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002665 // At this point we need AT to perform the expansions and we exit if it is
2666 // not available.
2667 unsigned ATReg = getATReg(IDLoc);
2668 if (!ATReg)
2669 return true;
2670 TmpReg = ATReg;
2671 }
2672
Daniel Sanders03f9c012015-07-14 12:24:22 +00002673 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002674 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002675 SrcReg = ZeroReg;
2676
2677 // This doesn't quite follow the usual ABI expectations for N32 but matches
2678 // traditional assembler behaviour. N32 would normally use addiu for both
2679 // integers and addresses.
2680 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002681 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002682 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002683 }
2684
Daniel Sandersa736b372016-04-29 13:33:12 +00002685 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002686 return false;
2687 }
2688
2689 if (isUInt<16>(ImmValue)) {
2690 unsigned TmpReg = DstReg;
2691 if (SrcReg == DstReg) {
2692 TmpReg = getATReg(IDLoc);
2693 if (!TmpReg)
2694 return true;
2695 }
2696
Daniel Sandersa736b372016-04-29 13:33:12 +00002697 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002698 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002699 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002700 return false;
2701 }
2702
2703 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002704 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002705
Toma Tabacu79588102015-04-29 10:19:56 +00002706 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2707 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002708 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002709 // Traditional behaviour seems to special case this particular value. It's
2710 // not clear why other masks are handled differently.
2711 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002712 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2713 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002714 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002715 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002716 return false;
2717 }
2718
2719 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002720 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002721 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2722 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002723 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002724 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002725 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002726 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002727 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002728 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002729
Daniel Sandersa736b372016-04-29 13:33:12 +00002730 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002731 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002732 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002733 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002734 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002735 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002736 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002737
2738 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2739 if (Is32BitImm) {
2740 Error(IDLoc, "instruction requires a 32-bit immediate");
2741 return true;
2742 }
2743
2744 // Traditionally, these immediates are shifted as little as possible and as
2745 // such we align the most significant bit to bit 15 of our temporary.
2746 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2747 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2748 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2749 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002750 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2751 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002752
2753 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002754 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002755
2756 return false;
2757 }
2758
2759 warnIfNoMacro(IDLoc);
2760
2761 // The remaining case is packed with a sequence of dsll and ori with zeros
2762 // being omitted and any neighbouring dsll's being coalesced.
2763 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2764
2765 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2766 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002767 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002768 return false;
2769
2770 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2771 // skip it and defer the shift to the next chunk.
2772 unsigned ShiftCarriedForwards = 16;
2773 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2774 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2775
2776 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002777 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2778 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002779 ShiftCarriedForwards = 0;
2780 }
2781
2782 ShiftCarriedForwards += 16;
2783 }
2784 ShiftCarriedForwards -= 16;
2785
2786 // Finish any remaining shifts left by trailing zeros.
2787 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002788 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002789
2790 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002791 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002792
Matheus Almeida3813d572014-06-19 14:39:14 +00002793 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002794}
Jack Carter92995f12012-10-06 00:53:28 +00002795
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002796bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002797 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002798 const MCOperand &ImmOp = Inst.getOperand(1);
2799 assert(ImmOp.isImm() && "expected immediate operand kind");
2800 const MCOperand &DstRegOp = Inst.getOperand(0);
2801 assert(DstRegOp.isReg() && "expected register operand kind");
2802
2803 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002804 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002805 return true;
2806
2807 return false;
2808}
2809
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002810bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2811 const MCOperand &Offset,
2812 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002813 MCStreamer &Out,
2814 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002815 // la can't produce a usable address when addresses are 64-bit.
2816 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2817 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2818 // We currently can't do this because we depend on the equality
2819 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2820 Error(IDLoc, "la used to load 64-bit address");
2821 // Continue as if we had 'dla' instead.
2822 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002823 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002824 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002825
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002826 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002827 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002828 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002829 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002830 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002831
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002832 if (!Offset.isImm())
2833 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002834 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002835
Scott Egerton24557012016-01-21 15:11:01 +00002836 if (!ABI.ArePtrs64bit()) {
2837 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2838 Is32BitAddress = true;
2839 }
2840
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002841 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002842 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002843}
2844
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002845bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2846 unsigned DstReg, unsigned SrcReg,
2847 bool Is32BitSym, SMLoc IDLoc,
2848 MCStreamer &Out,
2849 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002850 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002851 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002852 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002853 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002854
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002855 if (inPicMode() && ABI.IsO32()) {
2856 MCValue Res;
2857 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2858 Error(IDLoc, "expected relocatable expression");
2859 return true;
2860 }
2861 if (Res.getSymB() != nullptr) {
2862 Error(IDLoc, "expected relocatable expression with only one symbol");
2863 return true;
2864 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002865
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002866 // The case where the result register is $25 is somewhat special. If the
2867 // symbol in the final relocation is external and not modified with a
2868 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2869 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002870 Res.getConstant() == 0 &&
2871 !(Res.getSymA()->getSymbol().isInSection() ||
2872 Res.getSymA()->getSymbol().isTemporary() ||
2873 (Res.getSymA()->getSymbol().isELF() &&
2874 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2875 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002876 const MCExpr *CallExpr =
2877 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2878 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2879 MCOperand::createExpr(CallExpr), IDLoc, STI);
2880 return false;
2881 }
2882
2883 // The remaining cases are:
2884 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2885 // >addiu $tmp, $tmp, %lo(offset)
2886 // >addiu $rd, $tmp, $rs
2887 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2888 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2889 // >addiu $rd, $tmp, $rs
2890 // The addiu's marked with a '>' may be omitted if they are redundant. If
2891 // this happens then the last instruction must use $rd as the result
2892 // register.
2893 const MipsMCExpr *GotExpr =
2894 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2895 const MCExpr *LoExpr = nullptr;
2896 if (Res.getSymA()->getSymbol().isInSection() ||
2897 Res.getSymA()->getSymbol().isTemporary())
2898 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2899 else if (Res.getConstant() != 0) {
2900 // External symbols fully resolve the symbol with just the %got(symbol)
2901 // but we must still account for any offset to the symbol for expressions
2902 // like symbol+8.
2903 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2904 }
2905
2906 unsigned TmpReg = DstReg;
2907 if (UseSrcReg &&
2908 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2909 SrcReg)) {
2910 // If $rs is the same as $rd, we need to use AT.
2911 // If it is not available we exit.
2912 unsigned ATReg = getATReg(IDLoc);
2913 if (!ATReg)
2914 return true;
2915 TmpReg = ATReg;
2916 }
2917
2918 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2919 MCOperand::createExpr(GotExpr), IDLoc, STI);
2920
2921 if (LoExpr)
2922 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2923 IDLoc, STI);
2924
2925 if (UseSrcReg)
2926 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2927
2928 return false;
2929 }
2930
Simon Dardisda96c432017-06-30 15:44:27 +00002931 if (inPicMode() && ABI.ArePtrs64bit()) {
2932 MCValue Res;
2933 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2934 Error(IDLoc, "expected relocatable expression");
2935 return true;
2936 }
2937 if (Res.getSymB() != nullptr) {
2938 Error(IDLoc, "expected relocatable expression with only one symbol");
2939 return true;
2940 }
2941
2942 // The case where the result register is $25 is somewhat special. If the
2943 // symbol in the final relocation is external and not modified with a
2944 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2945 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2946 Res.getConstant() == 0 &&
2947 !(Res.getSymA()->getSymbol().isInSection() ||
2948 Res.getSymA()->getSymbol().isTemporary() ||
2949 (Res.getSymA()->getSymbol().isELF() &&
2950 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2951 ELF::STB_LOCAL))) {
2952 const MCExpr *CallExpr =
2953 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2954 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2955 MCOperand::createExpr(CallExpr), IDLoc, STI);
2956 return false;
2957 }
2958
2959 // The remaining cases are:
2960 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2961 // >daddiu $tmp, $tmp, offset
2962 // >daddu $rd, $tmp, $rs
2963 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2964 // this happens then the last instruction must use $rd as the result
2965 // register.
2966 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2967 Res.getSymA(),
2968 getContext());
2969 const MCExpr *LoExpr = nullptr;
2970 if (Res.getConstant() != 0) {
2971 // Symbols fully resolve with just the %got_disp(symbol) but we
2972 // must still account for any offset to the symbol for
2973 // expressions like symbol+8.
2974 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2975
2976 // FIXME: Offsets greater than 16 bits are not yet implemented.
2977 // FIXME: The correct range is a 32-bit sign-extended number.
2978 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2979 Error(IDLoc, "macro instruction uses large offset, which is not "
2980 "currently supported");
2981 return true;
2982 }
2983 }
2984
2985 unsigned TmpReg = DstReg;
2986 if (UseSrcReg &&
2987 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2988 SrcReg)) {
2989 // If $rs is the same as $rd, we need to use AT.
2990 // If it is not available we exit.
2991 unsigned ATReg = getATReg(IDLoc);
2992 if (!ATReg)
2993 return true;
2994 TmpReg = ATReg;
2995 }
2996
2997 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2998 MCOperand::createExpr(GotExpr), IDLoc, STI);
2999
3000 if (LoExpr)
3001 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3002 IDLoc, STI);
3003
3004 if (UseSrcReg)
3005 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
3006
3007 return false;
3008 }
3009
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003010 const MipsMCExpr *HiExpr =
3011 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3012 const MipsMCExpr *LoExpr =
3013 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00003014
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003015 // This is the 64-bit symbol address expansion.
3016 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00003017 // We need AT for the 64-bit expansion in the cases where the optional
3018 // source register is the destination register and for the superscalar
3019 // scheduled form.
3020 //
3021 // If it is not available we exit if the destination is the same as the
3022 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003023
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003024 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003025 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003026 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003027 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003028
Simon Dardis3aa8a902017-02-06 12:43:46 +00003029 bool RdRegIsRsReg =
3030 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3031
3032 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3033 unsigned ATReg = getATReg(IDLoc);
3034
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003035 // If $rs is the same as $rd:
3036 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3037 // daddiu $at, $at, %higher(sym)
3038 // dsll $at, $at, 16
3039 // daddiu $at, $at, %hi(sym)
3040 // dsll $at, $at, 16
3041 // daddiu $at, $at, %lo(sym)
3042 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003043 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3044 STI);
3045 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3046 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3047 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3048 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3049 IDLoc, STI);
3050 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3051 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3052 IDLoc, STI);
3053 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003054
3055 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003056 } else if (canUseATReg() && !RdRegIsRsReg) {
3057 unsigned ATReg = getATReg(IDLoc);
3058
3059 // If the $rs is different from $rd or if $rs isn't specified and we
3060 // have $at available:
3061 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3062 // lui $at, %hi(sym)
3063 // daddiu $rd, $rd, %higher(sym)
3064 // daddiu $at, $at, %lo(sym)
3065 // dsll32 $rd, $rd, 0
3066 // daddu $rd, $rd, $at
3067 // (daddu $rd, $rd, $rs)
3068 //
3069 // Which is preferred for superscalar issue.
3070 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3071 STI);
3072 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3073 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3074 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3075 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3076 IDLoc, STI);
3077 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3078 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3079 if (UseSrcReg)
3080 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3081
3082 return false;
3083 } else if (!canUseATReg() && !RdRegIsRsReg) {
3084 // Otherwise, synthesize the address in the destination register
3085 // serially:
3086 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3087 // daddiu $rd, $rd, %higher(sym)
3088 // dsll $rd, $rd, 16
3089 // daddiu $rd, $rd, %hi(sym)
3090 // dsll $rd, $rd, 16
3091 // daddiu $rd, $rd, %lo(sym)
3092 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3093 STI);
3094 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3095 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3096 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3097 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3098 MCOperand::createExpr(HiExpr), IDLoc, STI);
3099 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3100 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3101 MCOperand::createExpr(LoExpr), IDLoc, STI);
3102 if (UseSrcReg)
3103 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3104
3105 return false;
3106 } else {
3107 // We have a case where SrcReg == DstReg and we don't have $at
3108 // available. We can't expand this case, so error out appropriately.
3109 assert(SrcReg == DstReg && !canUseATReg() &&
3110 "Could have expanded dla but didn't?");
3111 reportParseError(IDLoc,
3112 "pseudo-instruction requires $at, which is not available");
3113 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003114 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003115 }
3116
3117 // And now, the 32-bit symbol address expansion:
3118 // If $rs is the same as $rd:
3119 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3120 // ori $at, $at, %lo(sym)
3121 // addu $rd, $at, $rd
3122 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3123 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3124 // ori $rd, $rd, %lo(sym)
3125 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003126 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003127 if (UseSrcReg &&
3128 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003129 // If $rs is the same as $rd, we need to use AT.
3130 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003131 unsigned ATReg = getATReg(IDLoc);
3132 if (!ATReg)
3133 return true;
3134 TmpReg = ATReg;
3135 }
3136
Daniel Sandersa736b372016-04-29 13:33:12 +00003137 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3138 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3139 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003140
Toma Tabacufb9d1252015-06-22 12:08:39 +00003141 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003142 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003143 else
Scott Egerton24557012016-01-21 15:11:01 +00003144 assert(
3145 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003146
Toma Tabacu674825c2015-06-16 12:16:24 +00003147 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003148}
3149
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003150// Each double-precision register DO-D15 overlaps with two of the single
3151// precision registers F0-F31. As an example, all of the following hold true:
3152// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3153static unsigned nextReg(unsigned Reg) {
3154 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3155 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3156 switch (Reg) {
3157 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3158 case Mips::ZERO: return Mips::AT;
3159 case Mips::AT: return Mips::V0;
3160 case Mips::V0: return Mips::V1;
3161 case Mips::V1: return Mips::A0;
3162 case Mips::A0: return Mips::A1;
3163 case Mips::A1: return Mips::A2;
3164 case Mips::A2: return Mips::A3;
3165 case Mips::A3: return Mips::T0;
3166 case Mips::T0: return Mips::T1;
3167 case Mips::T1: return Mips::T2;
3168 case Mips::T2: return Mips::T3;
3169 case Mips::T3: return Mips::T4;
3170 case Mips::T4: return Mips::T5;
3171 case Mips::T5: return Mips::T6;
3172 case Mips::T6: return Mips::T7;
3173 case Mips::T7: return Mips::S0;
3174 case Mips::S0: return Mips::S1;
3175 case Mips::S1: return Mips::S2;
3176 case Mips::S2: return Mips::S3;
3177 case Mips::S3: return Mips::S4;
3178 case Mips::S4: return Mips::S5;
3179 case Mips::S5: return Mips::S6;
3180 case Mips::S6: return Mips::S7;
3181 case Mips::S7: return Mips::T8;
3182 case Mips::T8: return Mips::T9;
3183 case Mips::T9: return Mips::K0;
3184 case Mips::K0: return Mips::K1;
3185 case Mips::K1: return Mips::GP;
3186 case Mips::GP: return Mips::SP;
3187 case Mips::SP: return Mips::FP;
3188 case Mips::FP: return Mips::RA;
3189 case Mips::RA: return Mips::ZERO;
3190 case Mips::D0: return Mips::F1;
3191 case Mips::D1: return Mips::F3;
3192 case Mips::D2: return Mips::F5;
3193 case Mips::D3: return Mips::F7;
3194 case Mips::D4: return Mips::F9;
3195 case Mips::D5: return Mips::F11;
3196 case Mips::D6: return Mips::F13;
3197 case Mips::D7: return Mips::F15;
3198 case Mips::D8: return Mips::F17;
3199 case Mips::D9: return Mips::F19;
3200 case Mips::D10: return Mips::F21;
3201 case Mips::D11: return Mips::F23;
3202 case Mips::D12: return Mips::F25;
3203 case Mips::D13: return Mips::F27;
3204 case Mips::D14: return Mips::F29;
3205 case Mips::D15: return Mips::F31;
3206 }
3207}
3208
3209// FIXME: This method is too general. In principle we should compute the number
3210// of instructions required to synthesize the immediate inline compared to
3211// synthesizing the address inline and relying on non .text sections.
3212// For static O32 and N32 this may yield a small benefit, for static N64 this is
3213// likely to yield a much larger benefit as we have to synthesize a 64bit
3214// address to load a 64 bit value.
3215bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3216 MCSymbol *Sym) {
3217 unsigned ATReg = getATReg(IDLoc);
3218 if (!ATReg)
3219 return true;
3220
3221 if(IsPicEnabled) {
3222 const MCExpr *GotSym =
3223 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3224 const MipsMCExpr *GotExpr =
3225 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3226
3227 if(isABI_O32() || isABI_N32()) {
3228 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3229 IDLoc, STI);
3230 } else { //isABI_N64()
3231 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3232 IDLoc, STI);
3233 }
3234 } else { //!IsPicEnabled
3235 const MCExpr *HiSym =
3236 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3237 const MipsMCExpr *HiExpr =
3238 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3239
3240 // FIXME: This is technically correct but gives a different result to gas,
3241 // but gas is incomplete there (it has a fixme noting it doesn't work with
3242 // 64-bit addresses).
3243 // FIXME: With -msym32 option, the address expansion for N64 should probably
3244 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3245 // symbol's value is considered sign extended.
3246 if(isABI_O32() || isABI_N32()) {
3247 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3248 } else { //isABI_N64()
3249 const MCExpr *HighestSym =
3250 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3251 const MipsMCExpr *HighestExpr =
3252 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3253 const MCExpr *HigherSym =
3254 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3255 const MipsMCExpr *HigherExpr =
3256 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3257
3258 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3259 STI);
3260 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3261 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3262 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3263 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3264 IDLoc, STI);
3265 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3266 }
3267 }
3268 return false;
3269}
3270
3271bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3272 bool Is64FPU, SMLoc IDLoc,
3273 MCStreamer &Out,
3274 const MCSubtargetInfo *STI) {
3275 MipsTargetStreamer &TOut = getTargetStreamer();
3276 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3277 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3278 "Invalid instruction operand.");
3279
3280 unsigned FirstReg = Inst.getOperand(0).getReg();
3281 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3282
3283 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3284 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3285 // exponent field), convert it to double (e.g. 1 to 1.0)
3286 if ((HiImmOp64 & 0x7ff00000) == 0) {
3287 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3288 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3289 }
3290
3291 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3292 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3293
3294 if (IsSingle) {
3295 // Conversion of a double in an uint64_t to a float in a uint32_t,
3296 // retaining the bit pattern of a float.
3297 uint32_t ImmOp32;
3298 double doubleImm = BitsToDouble(ImmOp64);
3299 float tmp_float = static_cast<float>(doubleImm);
3300 ImmOp32 = FloatToBits(tmp_float);
3301
3302 if (IsGPR) {
3303 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3304 Out, STI))
3305 return true;
3306 return false;
3307 } else {
3308 unsigned ATReg = getATReg(IDLoc);
3309 if (!ATReg)
3310 return true;
3311 if (LoImmOp64 == 0) {
3312 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3313 Out, STI))
3314 return true;
3315 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3316 return false;
3317 }
3318
3319 MCSection *CS = getStreamer().getCurrentSectionOnly();
3320 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3321 // where appropriate.
3322 MCSection *ReadOnlySection = getContext().getELFSection(
3323 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3324
3325 MCSymbol *Sym = getContext().createTempSymbol();
3326 const MCExpr *LoSym =
3327 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3328 const MipsMCExpr *LoExpr =
3329 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3330
3331 getStreamer().SwitchSection(ReadOnlySection);
3332 getStreamer().EmitLabel(Sym, IDLoc);
3333 getStreamer().EmitIntValue(ImmOp32, 4);
3334 getStreamer().SwitchSection(CS);
3335
3336 if(emitPartialAddress(TOut, IDLoc, Sym))
3337 return true;
3338 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3339 MCOperand::createExpr(LoExpr), IDLoc, STI);
3340 }
3341 return false;
3342 }
3343
3344 // if(!IsSingle)
3345 unsigned ATReg = getATReg(IDLoc);
3346 if (!ATReg)
3347 return true;
3348
3349 if (IsGPR) {
3350 if (LoImmOp64 == 0) {
3351 if(isABI_N32() || isABI_N64()) {
3352 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3353 IDLoc, Out, STI))
3354 return true;
3355 return false;
3356 } else {
3357 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3358 IDLoc, Out, STI))
3359 return true;
3360
3361 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3362 IDLoc, Out, STI))
3363 return true;
3364 return false;
3365 }
3366 }
3367
3368 MCSection *CS = getStreamer().getCurrentSectionOnly();
3369 MCSection *ReadOnlySection = getContext().getELFSection(
3370 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3371
3372 MCSymbol *Sym = getContext().createTempSymbol();
3373 const MCExpr *LoSym =
3374 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3375 const MipsMCExpr *LoExpr =
3376 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3377
3378 getStreamer().SwitchSection(ReadOnlySection);
3379 getStreamer().EmitLabel(Sym, IDLoc);
3380 getStreamer().EmitIntValue(HiImmOp64, 4);
3381 getStreamer().EmitIntValue(LoImmOp64, 4);
3382 getStreamer().SwitchSection(CS);
3383
3384 if(emitPartialAddress(TOut, IDLoc, Sym))
3385 return true;
3386 if(isABI_N64())
3387 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3388 MCOperand::createExpr(LoExpr), IDLoc, STI);
3389 else
3390 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3391 MCOperand::createExpr(LoExpr), IDLoc, STI);
3392
3393 if(isABI_N32() || isABI_N64())
3394 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3395 else {
3396 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3397 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3398 }
3399 return false;
3400 } else { // if(!IsGPR && !IsSingle)
3401 if ((LoImmOp64 == 0) &&
3402 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3403 // FIXME: In the case where the constant is zero, we can load the
3404 // register directly from the zero register.
3405 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3406 Out, STI))
3407 return true;
3408 if (isABI_N32() || isABI_N64())
3409 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3410 else if (hasMips32r2()) {
3411 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3412 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3413 } else {
3414 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3415 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3416 }
3417 return false;
3418 }
3419
3420 MCSection *CS = getStreamer().getCurrentSectionOnly();
3421 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3422 // where appropriate.
3423 MCSection *ReadOnlySection = getContext().getELFSection(
3424 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3425
3426 MCSymbol *Sym = getContext().createTempSymbol();
3427 const MCExpr *LoSym =
3428 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3429 const MipsMCExpr *LoExpr =
3430 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3431
3432 getStreamer().SwitchSection(ReadOnlySection);
3433 getStreamer().EmitLabel(Sym, IDLoc);
3434 getStreamer().EmitIntValue(HiImmOp64, 4);
3435 getStreamer().EmitIntValue(LoImmOp64, 4);
3436 getStreamer().SwitchSection(CS);
3437
3438 if(emitPartialAddress(TOut, IDLoc, Sym))
3439 return true;
3440 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3441 MCOperand::createExpr(LoExpr), IDLoc, STI);
3442 }
3443 return false;
3444}
3445
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003446bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3447 MCStreamer &Out,
3448 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003449 MipsTargetStreamer &TOut = getTargetStreamer();
3450
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003451 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3452 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003453
3454 MCOperand Offset = Inst.getOperand(0);
3455 if (Offset.isExpr()) {
3456 Inst.clear();
3457 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003458 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3459 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3460 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003461 } else {
3462 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003463 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003464 // If offset fits into 11 bits then this instruction becomes microMIPS
3465 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003466 if (inMicroMipsMode())
3467 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003468 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003469 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003470 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003471 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003472 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003473 Inst.clear();
3474 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003475 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3476 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3477 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003478 }
3479 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003480 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003481
Zoran Jovanovicada70912015-09-07 11:56:37 +00003482 // If .set reorder is active and branch instruction has a delay slot,
3483 // emit a NOP after it.
3484 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3485 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003486 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003487
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003488 return false;
3489}
3490
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003491bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3492 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003493 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003494 const MCOperand &DstRegOp = Inst.getOperand(0);
3495 assert(DstRegOp.isReg() && "expected register operand kind");
3496
3497 const MCOperand &ImmOp = Inst.getOperand(1);
3498 assert(ImmOp.isImm() && "expected immediate operand kind");
3499
3500 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003501 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3502 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003503
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003504 bool IsLikely = false;
3505
Toma Tabacue1e460d2015-06-11 10:36:10 +00003506 unsigned OpCode = 0;
3507 switch(Inst.getOpcode()) {
3508 case Mips::BneImm:
3509 OpCode = Mips::BNE;
3510 break;
3511 case Mips::BeqImm:
3512 OpCode = Mips::BEQ;
3513 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003514 case Mips::BEQLImmMacro:
3515 OpCode = Mips::BEQL;
3516 IsLikely = true;
3517 break;
3518 case Mips::BNELImmMacro:
3519 OpCode = Mips::BNEL;
3520 IsLikely = true;
3521 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003522 default:
3523 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3524 break;
3525 }
3526
3527 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003528 if (ImmValue == 0) {
3529 if (IsLikely) {
3530 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3531 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3532 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3533 } else
3534 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3535 STI);
3536 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003537 warnIfNoMacro(IDLoc);
3538
3539 unsigned ATReg = getATReg(IDLoc);
3540 if (!ATReg)
3541 return true;
3542
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003543 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003544 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003545 return true;
3546
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003547 if (IsLikely) {
3548 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3549 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3550 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3551 } else
3552 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003553 }
3554 return false;
3555}
3556
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003557void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003558 const MCSubtargetInfo *STI, bool IsLoad,
3559 bool IsImmOpnd) {
Simon Atanasyan478220f2018-05-24 07:36:00 +00003560 if (IsLoad)
Daniel Sandersfba875f2016-04-29 13:43:45 +00003561 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
Simon Atanasyan478220f2018-05-24 07:36:00 +00003562 else
3563 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003564}
3565
3566void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3567 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3568 MipsTargetStreamer &TOut = getTargetStreamer();
3569
3570 unsigned DstReg = Inst.getOperand(0).getReg();
3571 unsigned BaseReg = Inst.getOperand(1).getReg();
3572
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003573 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003574 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3575 unsigned DstRegClassID =
3576 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3577 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3578 (DstRegClassID == Mips::GPR64RegClassID);
3579
3580 if (IsImmOpnd) {
3581 // Try to use DstReg as the temporary.
3582 if (IsGPR && (BaseReg != DstReg)) {
3583 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3584 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3585 STI);
3586 return;
3587 }
3588
Matheus Almeida7de68e72014-06-18 14:46:05 +00003589 // At this point we need AT to perform the expansions and we exit if it is
3590 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003591 unsigned ATReg = getATReg(IDLoc);
3592 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003593 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003594
3595 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3596 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3597 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003598 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003599
Daniel Sandersfba875f2016-04-29 13:43:45 +00003600 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003601 MCOperand LoOperand = MCOperand::createExpr(
3602 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3603 MCOperand HiOperand = MCOperand::createExpr(
3604 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003605
3606 // Try to use DstReg as the temporary.
3607 if (IsGPR && (BaseReg != DstReg)) {
3608 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3609 LoOperand, DstReg, IDLoc, STI);
3610 return;
3611 }
3612
3613 // At this point we need AT to perform the expansions and we exit if it is
3614 // not available.
3615 unsigned ATReg = getATReg(IDLoc);
3616 if (!ATReg)
3617 return;
3618
3619 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3620 LoOperand, ATReg, IDLoc, STI);
3621}
3622
3623void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3624 const MCSubtargetInfo *STI,
3625 bool IsImmOpnd) {
3626 MipsTargetStreamer &TOut = getTargetStreamer();
3627
3628 unsigned SrcReg = Inst.getOperand(0).getReg();
3629 unsigned BaseReg = Inst.getOperand(1).getReg();
3630
Daniel Sanders241c6792016-05-12 14:01:50 +00003631 if (IsImmOpnd) {
3632 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3633 Inst.getOperand(2).getImm(),
3634 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3635 return;
3636 }
3637
Daniel Sandersfba875f2016-04-29 13:43:45 +00003638 unsigned ATReg = getATReg(IDLoc);
3639 if (!ATReg)
3640 return;
3641
Daniel Sandersfba875f2016-04-29 13:43:45 +00003642 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003643 MCOperand LoOperand = MCOperand::createExpr(
3644 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3645 MCOperand HiOperand = MCOperand::createExpr(
3646 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003647 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3648 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003649}
3650
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003651bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3652 MCStreamer &Out,
3653 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003654 unsigned OpNum = Inst.getNumOperands();
3655 unsigned Opcode = Inst.getOpcode();
3656 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3657
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003658 assert(Inst.getOperand(OpNum - 1).isImm() &&
3659 Inst.getOperand(OpNum - 2).isReg() &&
3660 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003661
3662 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3663 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003664 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3665 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3666 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3667 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003668 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003669 if (inMicroMipsMode() && hasMips32r6())
3670 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3671 else
3672 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3673 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003674
3675 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003676 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003677 return false;
3678}
3679
Toma Tabacu1a108322015-06-17 13:20:24 +00003680bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003681 MCStreamer &Out,
3682 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003683 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003684 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003685 unsigned PseudoOpcode = Inst.getOpcode();
3686 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003687 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003688 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3689
3690 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003691 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003692
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003693 unsigned TrgReg;
3694 if (TrgOp.isReg())
3695 TrgReg = TrgOp.getReg();
3696 else if (TrgOp.isImm()) {
3697 warnIfNoMacro(IDLoc);
3698 EmittedNoMacroWarning = true;
3699
3700 TrgReg = getATReg(IDLoc);
3701 if (!TrgReg)
3702 return true;
3703
3704 switch(PseudoOpcode) {
3705 default:
3706 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3707 case Mips::BLTImmMacro:
3708 PseudoOpcode = Mips::BLT;
3709 break;
3710 case Mips::BLEImmMacro:
3711 PseudoOpcode = Mips::BLE;
3712 break;
3713 case Mips::BGEImmMacro:
3714 PseudoOpcode = Mips::BGE;
3715 break;
3716 case Mips::BGTImmMacro:
3717 PseudoOpcode = Mips::BGT;
3718 break;
3719 case Mips::BLTUImmMacro:
3720 PseudoOpcode = Mips::BLTU;
3721 break;
3722 case Mips::BLEUImmMacro:
3723 PseudoOpcode = Mips::BLEU;
3724 break;
3725 case Mips::BGEUImmMacro:
3726 PseudoOpcode = Mips::BGEU;
3727 break;
3728 case Mips::BGTUImmMacro:
3729 PseudoOpcode = Mips::BGTU;
3730 break;
3731 case Mips::BLTLImmMacro:
3732 PseudoOpcode = Mips::BLTL;
3733 break;
3734 case Mips::BLELImmMacro:
3735 PseudoOpcode = Mips::BLEL;
3736 break;
3737 case Mips::BGELImmMacro:
3738 PseudoOpcode = Mips::BGEL;
3739 break;
3740 case Mips::BGTLImmMacro:
3741 PseudoOpcode = Mips::BGTL;
3742 break;
3743 case Mips::BLTULImmMacro:
3744 PseudoOpcode = Mips::BLTUL;
3745 break;
3746 case Mips::BLEULImmMacro:
3747 PseudoOpcode = Mips::BLEUL;
3748 break;
3749 case Mips::BGEULImmMacro:
3750 PseudoOpcode = Mips::BGEUL;
3751 break;
3752 case Mips::BGTULImmMacro:
3753 PseudoOpcode = Mips::BGTUL;
3754 break;
3755 }
3756
3757 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003758 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003759 return true;
3760 }
3761
Toma Tabacu1a108322015-06-17 13:20:24 +00003762 switch (PseudoOpcode) {
3763 case Mips::BLT:
3764 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003765 case Mips::BLTL:
3766 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003767 AcceptsEquality = false;
3768 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003769 IsUnsigned =
3770 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003771 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003772 ZeroSrcOpcode = Mips::BGTZ;
3773 ZeroTrgOpcode = Mips::BLTZ;
3774 break;
3775 case Mips::BLE:
3776 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003777 case Mips::BLEL:
3778 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003779 AcceptsEquality = true;
3780 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003781 IsUnsigned =
3782 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003783 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003784 ZeroSrcOpcode = Mips::BGEZ;
3785 ZeroTrgOpcode = Mips::BLEZ;
3786 break;
3787 case Mips::BGE:
3788 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003789 case Mips::BGEL:
3790 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003791 AcceptsEquality = true;
3792 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003793 IsUnsigned =
3794 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003795 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003796 ZeroSrcOpcode = Mips::BLEZ;
3797 ZeroTrgOpcode = Mips::BGEZ;
3798 break;
3799 case Mips::BGT:
3800 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003801 case Mips::BGTL:
3802 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003803 AcceptsEquality = false;
3804 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003805 IsUnsigned =
3806 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003807 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003808 ZeroSrcOpcode = Mips::BLTZ;
3809 ZeroTrgOpcode = Mips::BGTZ;
3810 break;
3811 default:
3812 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3813 }
3814
Toma Tabacu1a108322015-06-17 13:20:24 +00003815 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3816 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3817 if (IsSrcRegZero && IsTrgRegZero) {
3818 // FIXME: All of these Opcode-specific if's are needed for compatibility
3819 // with GAS' behaviour. However, they may not generate the most efficient
3820 // code in some circumstances.
3821 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003822 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3823 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003824 return false;
3825 }
3826 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003827 TOut.emitRX(Mips::BLEZ, 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::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003833 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3834 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003835 Warning(IDLoc, "branch is always taken");
3836 return false;
3837 }
3838 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003839 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3840 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003841 return false;
3842 }
3843 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003844 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3845 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003846 return false;
3847 }
3848 if (AcceptsEquality) {
3849 // If both registers are $0 and the pseudo-branch accepts equality, it
3850 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003851 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3852 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003853 Warning(IDLoc, "branch is always taken");
3854 return false;
3855 }
3856 // If both registers are $0 and the pseudo-branch does not accept
3857 // equality, it will never be taken, so we don't have to emit anything.
3858 return false;
3859 }
3860 if (IsSrcRegZero || IsTrgRegZero) {
3861 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3862 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3863 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3864 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3865 // the pseudo-branch will never be taken, so we don't emit anything.
3866 // This only applies to unsigned pseudo-branches.
3867 return false;
3868 }
3869 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3870 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3871 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3872 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3873 // the pseudo-branch will always be taken, so we emit an unconditional
3874 // branch.
3875 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003876 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3877 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003878 Warning(IDLoc, "branch is always taken");
3879 return false;
3880 }
3881 if (IsUnsigned) {
3882 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3883 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3884 // the pseudo-branch will be taken only when the non-zero register is
3885 // different from 0, so we emit a BNEZ.
3886 //
3887 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3888 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3889 // the pseudo-branch will be taken only when the non-zero register is
3890 // equal to 0, so we emit a BEQZ.
3891 //
3892 // Because only BLEU and BGEU branch on equality, we can use the
3893 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003894 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3895 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3896 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003897 return false;
3898 }
3899 // If we have a signed pseudo-branch and one of the registers is $0,
3900 // we can use an appropriate compare-to-zero branch. We select which one
3901 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003902 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3903 IsSrcRegZero ? TrgReg : SrcReg,
3904 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003905 return false;
3906 }
3907
3908 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3909 // expansions. If it is not available, we return.
3910 unsigned ATRegNum = getATReg(IDLoc);
3911 if (!ATRegNum)
3912 return true;
3913
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003914 if (!EmittedNoMacroWarning)
3915 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003916
3917 // SLT fits well with 2 of our 4 pseudo-branches:
3918 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3919 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3920 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3921 // This is accomplished by using a BNEZ with the result of the SLT.
3922 //
3923 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003924 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003925 // Because only BGE and BLE branch on equality, we can use the
3926 // AcceptsEquality variable to decide when to emit the BEQZ.
3927 // Note that the order of the SLT arguments doesn't change between
3928 // opposites.
3929 //
3930 // The same applies to the unsigned variants, except that SLTu is used
3931 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003932 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3933 ReverseOrderSLT ? TrgReg : SrcReg,
3934 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003935
Daniel Sandersa736b372016-04-29 13:33:12 +00003936 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3937 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3938 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3939 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003940 return false;
3941}
3942
Simon Dardis509da1a2017-02-13 16:06:48 +00003943// Expand a integer division macro.
3944//
3945// Notably we don't have to emit a warning when encountering $rt as the $zero
3946// register, or 0 as an immediate. processInstruction() has already done that.
3947//
3948// The destination register can only be $zero when expanding (S)DivIMacro or
3949// D(S)DivMacro.
3950
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003951bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3952 const MCSubtargetInfo *STI, const bool IsMips64,
3953 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003954 MipsTargetStreamer &TOut = getTargetStreamer();
3955
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003956 warnIfNoMacro(IDLoc);
3957
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003958 const MCOperand &RdRegOp = Inst.getOperand(0);
3959 assert(RdRegOp.isReg() && "expected register operand kind");
3960 unsigned RdReg = RdRegOp.getReg();
3961
3962 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003963 assert(RsRegOp.isReg() && "expected register operand kind");
3964 unsigned RsReg = RsRegOp.getReg();
3965
Simon Dardis12850ee2017-01-31 10:49:24 +00003966 unsigned RtReg;
3967 int64_t ImmValue;
3968
3969 const MCOperand &RtOp = Inst.getOperand(2);
3970 assert((RtOp.isReg() || RtOp.isImm()) &&
3971 "expected register or immediate operand kind");
3972 if (RtOp.isReg())
3973 RtReg = RtOp.getReg();
3974 else
3975 ImmValue = RtOp.getImm();
3976
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003977 unsigned DivOp;
3978 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003979 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003980
3981 if (IsMips64) {
3982 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3983 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003984 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003985 } else {
3986 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3987 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003988 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003989 }
3990
3991 bool UseTraps = useTraps();
3992
Simon Dardis12850ee2017-01-31 10:49:24 +00003993 if (RtOp.isImm()) {
3994 unsigned ATReg = getATReg(IDLoc);
3995 if (!ATReg)
3996 return true;
3997
3998 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003999 if (UseTraps)
4000 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
4001 else
4002 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4003 return false;
4004 }
4005
4006 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004007 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004008 return false;
4009 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004010 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004011 return false;
4012 } else {
4013 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4014 false, Inst.getLoc(), Out, STI))
4015 return true;
4016 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
4017 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
4018 return false;
4019 }
4020 return true;
4021 }
4022
Simon Dardis509da1a2017-02-13 16:06:48 +00004023 // If the macro expansion of (d)div(u) would always trap or break, insert
4024 // the trap/break and exit. This gives a different result to GAS. GAS has
4025 // an inconsistency/missed optimization in that not all cases are handled
4026 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004027 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004028 if (UseTraps) {
4029 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004030 return false;
4031 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004032 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4033 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004034 }
4035
Simon Dardis509da1a2017-02-13 16:06:48 +00004036 // Temporary label for first branch traget
4037 MCContext &Context = TOut.getStreamer().getContext();
4038 MCSymbol *BrTarget;
4039 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004040
4041 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004042 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004043 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004044 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004045 BrTarget = Context.createTempSymbol();
4046 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4047 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004048 }
4049
Daniel Sandersa736b372016-04-29 13:33:12 +00004050 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004051
4052 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004053 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004054
4055 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004056 if (!UseTraps)
4057 TOut.getStreamer().EmitLabel(BrTarget);
4058
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004059 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004060 return false;
4061 }
4062
4063 unsigned ATReg = getATReg(IDLoc);
4064 if (!ATReg)
4065 return true;
4066
Simon Dardis509da1a2017-02-13 16:06:48 +00004067 if (!UseTraps)
4068 TOut.getStreamer().EmitLabel(BrTarget);
4069
Daniel Sandersa736b372016-04-29 13:33:12 +00004070 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004071
4072 // Temporary label for the second branch target.
4073 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4074 MCOperand LabelOpEnd =
4075 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4076
4077 // Branch to the mflo instruction.
4078 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4079
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004080 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004081 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4082 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004083 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004084 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004085 }
4086
4087 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004088 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004089 else {
4090 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004091 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004092 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4093 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004094 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004095
4096 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004097 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004098 return false;
4099}
4100
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004101bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004102 SMLoc IDLoc, MCStreamer &Out,
4103 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004104 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004105
4106 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4107 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4108 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4109
4110 unsigned FirstReg = Inst.getOperand(0).getReg();
4111 unsigned SecondReg = Inst.getOperand(1).getReg();
4112 unsigned ThirdReg = Inst.getOperand(2).getReg();
4113
4114 if (hasMips1() && !hasMips2()) {
4115 unsigned ATReg = getATReg(IDLoc);
4116 if (!ATReg)
4117 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004118 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4119 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4120 TOut.emitNop(IDLoc, STI);
4121 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4122 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4123 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4124 TOut.emitNop(IDLoc, STI);
4125 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4126 : Mips::CVT_W_S,
4127 FirstReg, SecondReg, IDLoc, STI);
4128 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4129 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004130 return false;
4131 }
4132
Daniel Sandersa736b372016-04-29 13:33:12 +00004133 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4134 : Mips::TRUNC_W_S,
4135 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004136
4137 return false;
4138}
4139
Daniel Sanders6394ee52015-10-15 14:52:58 +00004140bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004141 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004142 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004143 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004144 }
4145
Toma Tabacud88d79c2015-06-23 14:39:42 +00004146 const MCOperand &DstRegOp = Inst.getOperand(0);
4147 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004148 const MCOperand &SrcRegOp = Inst.getOperand(1);
4149 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004150 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4151 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4152
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004153 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004154 unsigned DstReg = DstRegOp.getReg();
4155 unsigned SrcReg = SrcRegOp.getReg();
4156 int64_t OffsetValue = OffsetImmOp.getImm();
4157
4158 // NOTE: We always need AT for ULHU, as it is always used as the source
4159 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004160 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004161 unsigned ATReg = getATReg(IDLoc);
4162 if (!ATReg)
4163 return true;
4164
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004165 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4166 if (IsLargeOffset) {
4167 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4168 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004169 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004170 }
4171
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004172 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4173 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4174 if (isLittle())
4175 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004176
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004177 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4178 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004179
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004180 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4181 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004182
Daniel Sandersa736b372016-04-29 13:33:12 +00004183 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004184 FirstOffset, IDLoc, STI);
4185 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004186 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004187 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004188
4189 return false;
4190}
4191
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004192bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004193 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004194 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004195 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004196 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004197
4198 const MCOperand &DstRegOp = Inst.getOperand(0);
4199 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004200 const MCOperand &SrcRegOp = Inst.getOperand(1);
4201 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004202 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4203 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4204
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004205 MipsTargetStreamer &TOut = getTargetStreamer();
4206 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004207 unsigned SrcReg = SrcRegOp.getReg();
4208 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004209
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004210 warnIfNoMacro(IDLoc);
4211 unsigned ATReg = getATReg(IDLoc);
4212 if (!ATReg)
4213 return true;
4214
4215 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4216 if (IsLargeOffset) {
4217 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4218 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004219 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004220 }
4221
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004222 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4223 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4224 if (isLittle())
4225 std::swap(FirstOffset, SecondOffset);
4226
4227 if (IsLargeOffset) {
4228 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4229 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4230 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4231 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4232 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4233 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004234 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004235 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4236 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4237 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004238 }
4239
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004240 return false;
4241}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004242
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004243bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4244 const MCSubtargetInfo *STI) {
4245 if (hasMips32r6() || hasMips64r6()) {
4246 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4247 }
4248
4249 const MCOperand &DstRegOp = Inst.getOperand(0);
4250 assert(DstRegOp.isReg() && "expected register operand kind");
4251 const MCOperand &SrcRegOp = Inst.getOperand(1);
4252 assert(SrcRegOp.isReg() && "expected register operand kind");
4253 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4254 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4255
4256 MipsTargetStreamer &TOut = getTargetStreamer();
4257 unsigned DstReg = DstRegOp.getReg();
4258 unsigned SrcReg = SrcRegOp.getReg();
4259 int64_t OffsetValue = OffsetImmOp.getImm();
4260
4261 // Compute left/right load/store offsets.
4262 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4263 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4264 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4265 if (isLittle())
4266 std::swap(LxlOffset, LxrOffset);
4267
4268 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4269 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4270 unsigned TmpReg = SrcReg;
4271 if (IsLargeOffset || DoMove) {
4272 warnIfNoMacro(IDLoc);
4273 TmpReg = getATReg(IDLoc);
4274 if (!TmpReg)
4275 return true;
4276 }
4277
4278 if (IsLargeOffset) {
4279 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4280 IDLoc, Out, STI))
4281 return true;
4282 }
4283
4284 if (DoMove)
4285 std::swap(DstReg, TmpReg);
4286
4287 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4288 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4289 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4290 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4291
4292 if (DoMove)
4293 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004294
4295 return false;
4296}
4297
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004298bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004299 MCStreamer &Out,
4300 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004301 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004302
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004303 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4304 assert(Inst.getOperand(0).isReg() &&
4305 Inst.getOperand(1).isReg() &&
4306 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004307
4308 unsigned ATReg = Mips::NoRegister;
4309 unsigned FinalDstReg = Mips::NoRegister;
4310 unsigned DstReg = Inst.getOperand(0).getReg();
4311 unsigned SrcReg = Inst.getOperand(1).getReg();
4312 int64_t ImmValue = Inst.getOperand(2).getImm();
4313
Simon Dardisaa208812017-02-24 14:34:32 +00004314 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004315
4316 unsigned FinalOpcode = Inst.getOpcode();
4317
4318 if (DstReg == SrcReg) {
4319 ATReg = getATReg(Inst.getLoc());
4320 if (!ATReg)
4321 return true;
4322 FinalDstReg = DstReg;
4323 DstReg = ATReg;
4324 }
4325
Simon Atanasyan478220f2018-05-24 07:36:00 +00004326 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4327 Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004328 switch (FinalOpcode) {
4329 default:
4330 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004331 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004332 FinalOpcode = Mips::ADD;
4333 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004334 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004335 FinalOpcode = Mips::ADDu;
4336 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004337 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004338 FinalOpcode = Mips::AND;
4339 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004340 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004341 FinalOpcode = Mips::NOR;
4342 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004343 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004344 FinalOpcode = Mips::OR;
4345 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004346 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004347 FinalOpcode = Mips::SLT;
4348 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004349 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004350 FinalOpcode = Mips::SLTu;
4351 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004352 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004353 FinalOpcode = Mips::XOR;
4354 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004355 case Mips::ADDi_MM:
4356 FinalOpcode = Mips::ADD_MM;
4357 break;
4358 case Mips::ADDiu_MM:
4359 FinalOpcode = Mips::ADDu_MM;
4360 break;
4361 case Mips::ANDi_MM:
4362 FinalOpcode = Mips::AND_MM;
4363 break;
4364 case Mips::ORi_MM:
4365 FinalOpcode = Mips::OR_MM;
4366 break;
4367 case Mips::SLTi_MM:
4368 FinalOpcode = Mips::SLT_MM;
4369 break;
4370 case Mips::SLTiu_MM:
4371 FinalOpcode = Mips::SLTu_MM;
4372 break;
4373 case Mips::XORi_MM:
4374 FinalOpcode = Mips::XOR_MM;
4375 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004376 case Mips::ANDi64:
4377 FinalOpcode = Mips::AND64;
4378 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004379 case Mips::NORImm64:
4380 FinalOpcode = Mips::NOR64;
4381 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004382 case Mips::ORi64:
4383 FinalOpcode = Mips::OR64;
4384 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004385 case Mips::SLTImm64:
4386 FinalOpcode = Mips::SLT64;
4387 break;
4388 case Mips::SLTUImm64:
4389 FinalOpcode = Mips::SLTu64;
4390 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004391 case Mips::XORi64:
4392 FinalOpcode = Mips::XOR64;
4393 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004394 }
4395
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004396 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004397 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004398 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004399 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004400 return false;
4401 }
4402 return true;
4403}
4404
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004405bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4406 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004407 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004408 unsigned ATReg = Mips::NoRegister;
4409 unsigned DReg = Inst.getOperand(0).getReg();
4410 unsigned SReg = Inst.getOperand(1).getReg();
4411 unsigned TReg = Inst.getOperand(2).getReg();
4412 unsigned TmpReg = DReg;
4413
4414 unsigned FirstShift = Mips::NOP;
4415 unsigned SecondShift = Mips::NOP;
4416
4417 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004418 if (DReg == SReg) {
4419 TmpReg = getATReg(Inst.getLoc());
4420 if (!TmpReg)
4421 return true;
4422 }
4423
4424 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004425 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4426 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004427 return false;
4428 }
4429
4430 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004431 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004432 return false;
4433 }
4434
4435 return true;
4436 }
4437
4438 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004439 switch (Inst.getOpcode()) {
4440 default:
4441 llvm_unreachable("unexpected instruction opcode");
4442 case Mips::ROL:
4443 FirstShift = Mips::SRLV;
4444 SecondShift = Mips::SLLV;
4445 break;
4446 case Mips::ROR:
4447 FirstShift = Mips::SLLV;
4448 SecondShift = Mips::SRLV;
4449 break;
4450 }
4451
4452 ATReg = getATReg(Inst.getLoc());
4453 if (!ATReg)
4454 return true;
4455
Daniel Sandersa736b372016-04-29 13:33:12 +00004456 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4457 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4458 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4459 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004460
4461 return false;
4462 }
4463
4464 return true;
4465}
4466
4467bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004468 MCStreamer &Out,
4469 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004470 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004471 unsigned ATReg = Mips::NoRegister;
4472 unsigned DReg = Inst.getOperand(0).getReg();
4473 unsigned SReg = Inst.getOperand(1).getReg();
4474 int64_t ImmValue = Inst.getOperand(2).getImm();
4475
4476 unsigned FirstShift = Mips::NOP;
4477 unsigned SecondShift = Mips::NOP;
4478
4479 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004480 if (Inst.getOpcode() == Mips::ROLImm) {
4481 uint64_t MaxShift = 32;
4482 uint64_t ShiftValue = ImmValue;
4483 if (ImmValue != 0)
4484 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004485 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004486 return false;
4487 }
4488
4489 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004490 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004491 return false;
4492 }
4493
4494 return true;
4495 }
4496
4497 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004498 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004499 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004500 return false;
4501 }
4502
4503 switch (Inst.getOpcode()) {
4504 default:
4505 llvm_unreachable("unexpected instruction opcode");
4506 case Mips::ROLImm:
4507 FirstShift = Mips::SLL;
4508 SecondShift = Mips::SRL;
4509 break;
4510 case Mips::RORImm:
4511 FirstShift = Mips::SRL;
4512 SecondShift = Mips::SLL;
4513 break;
4514 }
4515
4516 ATReg = getATReg(Inst.getLoc());
4517 if (!ATReg)
4518 return true;
4519
Daniel Sandersa736b372016-04-29 13:33:12 +00004520 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4521 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4522 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004523
4524 return false;
4525 }
4526
4527 return true;
4528}
4529
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004530bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4531 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004532 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004533 unsigned ATReg = Mips::NoRegister;
4534 unsigned DReg = Inst.getOperand(0).getReg();
4535 unsigned SReg = Inst.getOperand(1).getReg();
4536 unsigned TReg = Inst.getOperand(2).getReg();
4537 unsigned TmpReg = DReg;
4538
4539 unsigned FirstShift = Mips::NOP;
4540 unsigned SecondShift = Mips::NOP;
4541
4542 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004543 if (TmpReg == SReg) {
4544 TmpReg = getATReg(Inst.getLoc());
4545 if (!TmpReg)
4546 return true;
4547 }
4548
4549 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004550 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4551 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004552 return false;
4553 }
4554
4555 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004556 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004557 return false;
4558 }
4559
4560 return true;
4561 }
4562
4563 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004564 switch (Inst.getOpcode()) {
4565 default:
4566 llvm_unreachable("unexpected instruction opcode");
4567 case Mips::DROL:
4568 FirstShift = Mips::DSRLV;
4569 SecondShift = Mips::DSLLV;
4570 break;
4571 case Mips::DROR:
4572 FirstShift = Mips::DSLLV;
4573 SecondShift = Mips::DSRLV;
4574 break;
4575 }
4576
4577 ATReg = getATReg(Inst.getLoc());
4578 if (!ATReg)
4579 return true;
4580
Daniel Sandersa736b372016-04-29 13:33:12 +00004581 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4582 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4583 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4584 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004585
4586 return false;
4587 }
4588
4589 return true;
4590}
4591
4592bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004593 MCStreamer &Out,
4594 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004595 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004596 unsigned ATReg = Mips::NoRegister;
4597 unsigned DReg = Inst.getOperand(0).getReg();
4598 unsigned SReg = Inst.getOperand(1).getReg();
4599 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4600
4601 unsigned FirstShift = Mips::NOP;
4602 unsigned SecondShift = Mips::NOP;
4603
4604 MCInst TmpInst;
4605
4606 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004607 unsigned FinalOpcode = Mips::NOP;
4608 if (ImmValue == 0)
4609 FinalOpcode = Mips::DROTR;
4610 else if (ImmValue % 32 == 0)
4611 FinalOpcode = Mips::DROTR32;
4612 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4613 if (Inst.getOpcode() == Mips::DROLImm)
4614 FinalOpcode = Mips::DROTR32;
4615 else
4616 FinalOpcode = Mips::DROTR;
4617 } else if (ImmValue >= 33) {
4618 if (Inst.getOpcode() == Mips::DROLImm)
4619 FinalOpcode = Mips::DROTR;
4620 else
4621 FinalOpcode = Mips::DROTR32;
4622 }
4623
4624 uint64_t ShiftValue = ImmValue % 32;
4625 if (Inst.getOpcode() == Mips::DROLImm)
4626 ShiftValue = (32 - ImmValue % 32) % 32;
4627
Daniel Sandersa736b372016-04-29 13:33:12 +00004628 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004629
4630 return false;
4631 }
4632
4633 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004634 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004635 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004636 return false;
4637 }
4638
4639 switch (Inst.getOpcode()) {
4640 default:
4641 llvm_unreachable("unexpected instruction opcode");
4642 case Mips::DROLImm:
4643 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4644 FirstShift = Mips::DSLL;
4645 SecondShift = Mips::DSRL32;
4646 }
4647 if (ImmValue == 32) {
4648 FirstShift = Mips::DSLL32;
4649 SecondShift = Mips::DSRL32;
4650 }
4651 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4652 FirstShift = Mips::DSLL32;
4653 SecondShift = Mips::DSRL;
4654 }
4655 break;
4656 case Mips::DRORImm:
4657 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4658 FirstShift = Mips::DSRL;
4659 SecondShift = Mips::DSLL32;
4660 }
4661 if (ImmValue == 32) {
4662 FirstShift = Mips::DSRL32;
4663 SecondShift = Mips::DSLL32;
4664 }
4665 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4666 FirstShift = Mips::DSRL32;
4667 SecondShift = Mips::DSLL;
4668 }
4669 break;
4670 }
4671
4672 ATReg = getATReg(Inst.getLoc());
4673 if (!ATReg)
4674 return true;
4675
Daniel Sandersa736b372016-04-29 13:33:12 +00004676 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4677 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4678 Inst.getLoc(), STI);
4679 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004680
4681 return false;
4682 }
4683
4684 return true;
4685}
4686
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004687bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4688 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004689 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004690 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4691 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4692
Daniel Sandersa736b372016-04-29 13:33:12 +00004693 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004694 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004695 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004696 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004697 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4698 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004699
4700 return false;
4701}
4702
Simon Dardis3c82a642017-02-08 16:25:05 +00004703bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4704 const MCSubtargetInfo *STI) {
4705 MipsTargetStreamer &TOut = getTargetStreamer();
4706 unsigned ATReg = Mips::NoRegister;
4707 unsigned DstReg = Inst.getOperand(0).getReg();
4708 unsigned SrcReg = Inst.getOperand(1).getReg();
4709 int32_t ImmValue = Inst.getOperand(2).getImm();
4710
4711 ATReg = getATReg(IDLoc);
4712 if (!ATReg)
4713 return true;
4714
Simon Atanasyan478220f2018-05-24 07:36:00 +00004715 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
4716 STI);
Simon Dardis3c82a642017-02-08 16:25:05 +00004717
4718 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4719 SrcReg, ATReg, IDLoc, STI);
4720
4721 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4722
4723 return false;
4724}
4725
4726bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4727 const MCSubtargetInfo *STI) {
4728 MipsTargetStreamer &TOut = getTargetStreamer();
4729 unsigned ATReg = Mips::NoRegister;
4730 unsigned DstReg = Inst.getOperand(0).getReg();
4731 unsigned SrcReg = Inst.getOperand(1).getReg();
4732 unsigned TmpReg = Inst.getOperand(2).getReg();
4733
4734 ATReg = getATReg(Inst.getLoc());
4735 if (!ATReg)
4736 return true;
4737
4738 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4739 SrcReg, TmpReg, IDLoc, STI);
4740
4741 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4742
4743 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4744 DstReg, DstReg, 0x1F, IDLoc, STI);
4745
4746 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4747
4748 if (useTraps()) {
4749 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4750 } else {
4751 MCContext & Context = TOut.getStreamer().getContext();
4752 MCSymbol * BrTarget = Context.createTempSymbol();
4753 MCOperand LabelOp =
4754 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4755
4756 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4757 if (AssemblerOptions.back()->isReorder())
4758 TOut.emitNop(IDLoc, STI);
4759 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4760
4761 TOut.getStreamer().EmitLabel(BrTarget);
4762 }
4763 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4764
4765 return false;
4766}
4767
4768bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4769 const MCSubtargetInfo *STI) {
4770 MipsTargetStreamer &TOut = getTargetStreamer();
4771 unsigned ATReg = Mips::NoRegister;
4772 unsigned DstReg = Inst.getOperand(0).getReg();
4773 unsigned SrcReg = Inst.getOperand(1).getReg();
4774 unsigned TmpReg = Inst.getOperand(2).getReg();
4775
4776 ATReg = getATReg(IDLoc);
4777 if (!ATReg)
4778 return true;
4779
4780 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4781 SrcReg, TmpReg, IDLoc, STI);
4782
4783 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4784 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4785 if (useTraps()) {
4786 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4787 } else {
4788 MCContext & Context = TOut.getStreamer().getContext();
4789 MCSymbol * BrTarget = Context.createTempSymbol();
4790 MCOperand LabelOp =
4791 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4792
4793 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4794 if (AssemblerOptions.back()->isReorder())
4795 TOut.emitNop(IDLoc, STI);
4796 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4797
4798 TOut.getStreamer().EmitLabel(BrTarget);
4799 }
4800
4801 return false;
4802}
4803
4804bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4805 const MCSubtargetInfo *STI) {
4806 MipsTargetStreamer &TOut = getTargetStreamer();
4807 unsigned DstReg = Inst.getOperand(0).getReg();
4808 unsigned SrcReg = Inst.getOperand(1).getReg();
4809 unsigned TmpReg = Inst.getOperand(2).getReg();
4810
4811 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4812 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4813
4814 return false;
4815}
4816
Simon Dardisaff4d142016-10-18 14:28:00 +00004817// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4818// lw $<reg+1>>, offset+4($reg2)'
4819// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4820// sw $<reg+1>>, offset+4($reg2)'
4821// for O32.
4822bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4823 MCStreamer &Out,
4824 const MCSubtargetInfo *STI,
4825 bool IsLoad) {
4826 if (!isABI_O32())
4827 return true;
4828
4829 warnIfNoMacro(IDLoc);
4830
4831 MipsTargetStreamer &TOut = getTargetStreamer();
4832 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4833 unsigned FirstReg = Inst.getOperand(0).getReg();
4834 unsigned SecondReg = nextReg(FirstReg);
4835 unsigned BaseReg = Inst.getOperand(1).getReg();
4836 if (!SecondReg)
4837 return true;
4838
4839 warnIfRegIndexIsAT(FirstReg, IDLoc);
4840
4841 assert(Inst.getOperand(2).isImm() &&
4842 "Offset for load macro is not immediate!");
4843
4844 MCOperand &FirstOffset = Inst.getOperand(2);
4845 signed NextOffset = FirstOffset.getImm() + 4;
4846 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4847
4848 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4849 return true;
4850
4851 // For loads, clobber the base register with the second load instead of the
4852 // first if the BaseReg == FirstReg.
4853 if (FirstReg != BaseReg || !IsLoad) {
4854 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4855 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4856 } else {
4857 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4858 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4859 }
4860
4861 return false;
4862}
4863
Simon Dardis43115a12016-11-21 20:30:41 +00004864bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4865 const MCSubtargetInfo *STI) {
4866
4867 warnIfNoMacro(IDLoc);
4868 MipsTargetStreamer &TOut = getTargetStreamer();
4869
4870 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4871 Inst.getOperand(2).getReg() != Mips::ZERO) {
4872 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4873 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4874 IDLoc, STI);
4875 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4876 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4877 return false;
4878 }
4879
4880 unsigned Reg = 0;
4881 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4882 Reg = Inst.getOperand(2).getReg();
4883 } else {
4884 Reg = Inst.getOperand(1).getReg();
4885 }
4886 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4887 return false;
4888}
4889
4890bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4891 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004892 warnIfNoMacro(IDLoc);
4893 MipsTargetStreamer &TOut = getTargetStreamer();
4894
4895 unsigned Opc;
4896 int64_t Imm = Inst.getOperand(2).getImm();
4897 unsigned Reg = Inst.getOperand(1).getReg();
4898
4899 if (Imm == 0) {
4900 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4901 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4902 return false;
4903 } else {
4904
4905 if (Reg == Mips::ZERO) {
4906 Warning(IDLoc, "comparison is always false");
4907 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4908 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4909 return false;
4910 }
4911
4912 if (Imm > -0x8000 && Imm < 0) {
4913 Imm = -Imm;
4914 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4915 } else {
4916 Opc = Mips::XORi;
4917 }
4918 }
4919 if (!isUInt<16>(Imm)) {
4920 unsigned ATReg = getATReg(IDLoc);
4921 if (!ATReg)
4922 return true;
4923
4924 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4925 Out, STI))
4926 return true;
4927
4928 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4929 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4930 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4931 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4932 return false;
4933 }
4934
4935 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4936 Imm, IDLoc, STI);
4937 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4938 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4939 return false;
4940}
4941
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004942// Map the DSP accumulator and control register to the corresponding gpr
4943// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4944// do not map the DSP registers contigously to gpr registers.
4945static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4946 switch (Inst.getOpcode()) {
4947 case Mips::MFTLO:
4948 case Mips::MTTLO:
4949 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4950 case Mips::AC0:
4951 return Mips::ZERO;
4952 case Mips::AC1:
4953 return Mips::A0;
4954 case Mips::AC2:
4955 return Mips::T0;
4956 case Mips::AC3:
4957 return Mips::T4;
4958 default:
4959 llvm_unreachable("Unknown register for 'mttr' alias!");
4960 }
4961 case Mips::MFTHI:
4962 case Mips::MTTHI:
4963 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4964 case Mips::AC0:
4965 return Mips::AT;
4966 case Mips::AC1:
4967 return Mips::A1;
4968 case Mips::AC2:
4969 return Mips::T1;
4970 case Mips::AC3:
4971 return Mips::T5;
4972 default:
4973 llvm_unreachable("Unknown register for 'mttr' alias!");
4974 }
4975 case Mips::MFTACX:
4976 case Mips::MTTACX:
4977 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4978 case Mips::AC0:
4979 return Mips::V0;
4980 case Mips::AC1:
4981 return Mips::A2;
4982 case Mips::AC2:
4983 return Mips::T2;
4984 case Mips::AC3:
4985 return Mips::T6;
4986 default:
4987 llvm_unreachable("Unknown register for 'mttr' alias!");
4988 }
4989 case Mips::MFTDSP:
4990 case Mips::MTTDSP:
4991 return Mips::S0;
4992 default:
4993 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4994 }
4995}
4996
4997// Map the floating point register operand to the corresponding register
4998// operand.
4999static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
5000 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
5001 case Mips::F0: return Mips::ZERO;
5002 case Mips::F1: return Mips::AT;
5003 case Mips::F2: return Mips::V0;
5004 case Mips::F3: return Mips::V1;
5005 case Mips::F4: return Mips::A0;
5006 case Mips::F5: return Mips::A1;
5007 case Mips::F6: return Mips::A2;
5008 case Mips::F7: return Mips::A3;
5009 case Mips::F8: return Mips::T0;
5010 case Mips::F9: return Mips::T1;
5011 case Mips::F10: return Mips::T2;
5012 case Mips::F11: return Mips::T3;
5013 case Mips::F12: return Mips::T4;
5014 case Mips::F13: return Mips::T5;
5015 case Mips::F14: return Mips::T6;
5016 case Mips::F15: return Mips::T7;
5017 case Mips::F16: return Mips::S0;
5018 case Mips::F17: return Mips::S1;
5019 case Mips::F18: return Mips::S2;
5020 case Mips::F19: return Mips::S3;
5021 case Mips::F20: return Mips::S4;
5022 case Mips::F21: return Mips::S5;
5023 case Mips::F22: return Mips::S6;
5024 case Mips::F23: return Mips::S7;
5025 case Mips::F24: return Mips::T8;
5026 case Mips::F25: return Mips::T9;
5027 case Mips::F26: return Mips::K0;
5028 case Mips::F27: return Mips::K1;
5029 case Mips::F28: return Mips::GP;
5030 case Mips::F29: return Mips::SP;
5031 case Mips::F30: return Mips::FP;
5032 case Mips::F31: return Mips::RA;
5033 default: llvm_unreachable("Unknown register for mttc1 alias!");
5034 }
5035}
5036
5037// Map the coprocessor operand the corresponding gpr register operand.
5038static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5039 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5040 case Mips::COP00: return Mips::ZERO;
5041 case Mips::COP01: return Mips::AT;
5042 case Mips::COP02: return Mips::V0;
5043 case Mips::COP03: return Mips::V1;
5044 case Mips::COP04: return Mips::A0;
5045 case Mips::COP05: return Mips::A1;
5046 case Mips::COP06: return Mips::A2;
5047 case Mips::COP07: return Mips::A3;
5048 case Mips::COP08: return Mips::T0;
5049 case Mips::COP09: return Mips::T1;
5050 case Mips::COP010: return Mips::T2;
5051 case Mips::COP011: return Mips::T3;
5052 case Mips::COP012: return Mips::T4;
5053 case Mips::COP013: return Mips::T5;
5054 case Mips::COP014: return Mips::T6;
5055 case Mips::COP015: return Mips::T7;
5056 case Mips::COP016: return Mips::S0;
5057 case Mips::COP017: return Mips::S1;
5058 case Mips::COP018: return Mips::S2;
5059 case Mips::COP019: return Mips::S3;
5060 case Mips::COP020: return Mips::S4;
5061 case Mips::COP021: return Mips::S5;
5062 case Mips::COP022: return Mips::S6;
5063 case Mips::COP023: return Mips::S7;
5064 case Mips::COP024: return Mips::T8;
5065 case Mips::COP025: return Mips::T9;
5066 case Mips::COP026: return Mips::K0;
5067 case Mips::COP027: return Mips::K1;
5068 case Mips::COP028: return Mips::GP;
5069 case Mips::COP029: return Mips::SP;
5070 case Mips::COP030: return Mips::FP;
5071 case Mips::COP031: return Mips::RA;
5072 default: llvm_unreachable("Unknown register for mttc0 alias!");
5073 }
5074}
5075
5076/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5077/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5078bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5079 const MCSubtargetInfo *STI) {
5080 MipsTargetStreamer &TOut = getTargetStreamer();
5081 unsigned rd = 0;
5082 unsigned u = 1;
5083 unsigned sel = 0;
5084 unsigned h = 0;
5085 bool IsMFTR = false;
5086 switch (Inst.getOpcode()) {
5087 case Mips::MFTC0:
5088 IsMFTR = true;
5089 LLVM_FALLTHROUGH;
5090 case Mips::MTTC0:
5091 u = 0;
5092 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5093 sel = Inst.getOperand(2).getImm();
5094 break;
5095 case Mips::MFTGPR:
5096 IsMFTR = true;
5097 LLVM_FALLTHROUGH;
5098 case Mips::MTTGPR:
5099 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5100 break;
5101 case Mips::MFTLO:
5102 case Mips::MFTHI:
5103 case Mips::MFTACX:
5104 case Mips::MFTDSP:
5105 IsMFTR = true;
5106 LLVM_FALLTHROUGH;
5107 case Mips::MTTLO:
5108 case Mips::MTTHI:
5109 case Mips::MTTACX:
5110 case Mips::MTTDSP:
5111 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5112 sel = 1;
5113 break;
5114 case Mips::MFTHC1:
5115 h = 1;
5116 LLVM_FALLTHROUGH;
5117 case Mips::MFTC1:
5118 IsMFTR = true;
5119 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5120 sel = 2;
5121 break;
5122 case Mips::MTTHC1:
5123 h = 1;
5124 LLVM_FALLTHROUGH;
5125 case Mips::MTTC1:
5126 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5127 sel = 2;
5128 break;
5129 case Mips::CFTC1:
5130 IsMFTR = true;
5131 LLVM_FALLTHROUGH;
5132 case Mips::CTTC1:
5133 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5134 sel = 3;
5135 break;
5136 }
5137 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5138 unsigned Op1 =
5139 IsMFTR ? rd
5140 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5141 : Inst.getOperand(0).getReg());
5142
5143 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5144 STI);
5145 return false;
5146}
5147
Daniel Sandersc5537422016-07-27 13:49:44 +00005148unsigned
5149MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5150 const OperandVector &Operands) {
5151 switch (Inst.getOpcode()) {
5152 default:
5153 return Match_Success;
5154 case Mips::DATI:
5155 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005156 if (static_cast<MipsOperand &>(*Operands[1])
5157 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5158 return Match_Success;
5159 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005160 }
5161}
Simon Dardis730fdb72017-01-16 13:55:58 +00005162
Matheus Almeida595fcab2014-06-11 15:05:56 +00005163unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005164 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005165 // As described by the MIPSR6 spec, daui must not use the zero operand for
5166 // its source operand.
5167 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005168 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5169 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5170 return Match_RequiresNoZeroRegister;
5171 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005172 // As described by the Mips32r2 spec, the registers Rd and Rs for
5173 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005174 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005175 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005176 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005177 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005178 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005179 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005180 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5181 return Match_RequiresDifferentSrcAndDst;
5182 return Match_Success;
5183 case Mips::LWP_MM:
5184 case Mips::LWP_MMR6:
5185 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5186 return Match_RequiresDifferentSrcAndDst;
5187 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005188 case Mips::SYNC:
5189 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5190 return Match_NonZeroOperandForSync;
5191 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005192 case Mips::MFC0:
5193 case Mips::MTC0:
5194 case Mips::MTC2:
5195 case Mips::MFC2:
5196 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5197 return Match_NonZeroOperandForMTCX;
5198 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005199 // As described the MIPSR6 spec, the compact branches that compare registers
5200 // must:
5201 // a) Not use the zero register.
5202 // b) Not use the same register twice.
5203 // c) rs < rt for bnec, beqc.
5204 // NB: For this case, the encoding will swap the operands as their
5205 // ordering doesn't matter. GAS performs this transformation too.
5206 // Hence, that constraint does not have to be enforced.
5207 //
5208 // The compact branches that branch iff the signed addition of two registers
5209 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5210 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005211 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5212 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5213 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5214 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5215 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5216 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005217 case Mips::BLEZC64:
5218 case Mips::BGEZC64:
5219 case Mips::BGTZC64:
5220 case Mips::BLTZC64:
5221 case Mips::BEQZC64:
5222 case Mips::BNEZC64:
5223 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5224 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005225 return Match_RequiresNoZeroRegister;
5226 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005227 case Mips::BGEC: case Mips::BGEC_MMR6:
5228 case Mips::BLTC: case Mips::BLTC_MMR6:
5229 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5230 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5231 case Mips::BEQC: case Mips::BEQC_MMR6:
5232 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005233 case Mips::BGEC64:
5234 case Mips::BLTC64:
5235 case Mips::BGEUC64:
5236 case Mips::BLTUC64:
5237 case Mips::BEQC64:
5238 case Mips::BNEC64:
5239 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5240 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005241 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005242 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5243 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005244 return Match_RequiresNoZeroRegister;
5245 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5246 return Match_RequiresDifferentOperands;
5247 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005248 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005249 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5250 "Operands must be immediates for dins!");
5251 const signed Pos = Inst.getOperand(2).getImm();
5252 const signed Size = Inst.getOperand(3).getImm();
5253 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5254 return Match_RequiresPosSizeRange0_32;
5255 return Match_Success;
5256 }
5257 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005258 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005259 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5260 "Operands must be immediates for dinsm/dinsu!");
5261 const signed Pos = Inst.getOperand(2).getImm();
5262 const signed Size = Inst.getOperand(3).getImm();
5263 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5264 return Match_RequiresPosSizeRange33_64;
5265 return Match_Success;
5266 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005267 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005268 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5269 "Operands must be immediates for DEXTM!");
5270 const signed Pos = Inst.getOperand(2).getImm();
5271 const signed Size = Inst.getOperand(3).getImm();
5272 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5273 return Match_RequiresPosSizeUImm6;
5274 return Match_Success;
5275 }
5276 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005277 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005278 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5279 "Operands must be immediates for dextm/dextu!");
5280 const signed Pos = Inst.getOperand(2).getImm();
5281 const signed Size = Inst.getOperand(3).getImm();
5282 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5283 return Match_RequiresPosSizeRange33_64;
5284 return Match_Success;
5285 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005286 case Mips::CRC32B: case Mips::CRC32CB:
5287 case Mips::CRC32H: case Mips::CRC32CH:
5288 case Mips::CRC32W: case Mips::CRC32CW:
5289 case Mips::CRC32D: case Mips::CRC32CD:
5290 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5291 return Match_RequiresSameSrcAndDst;
5292 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005293 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005294
5295 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5296 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5297 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5298 return Match_NoFCCRegisterForCurrentISA;
5299
5300 return Match_Success;
5301
Matheus Almeida595fcab2014-06-11 15:05:56 +00005302}
5303
Daniel Sanders52da7af2015-11-06 12:11:03 +00005304static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5305 uint64_t ErrorInfo) {
5306 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5307 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5308 if (ErrorLoc == SMLoc())
5309 return Loc;
5310 return ErrorLoc;
5311 }
5312 return Loc;
5313}
5314
David Blaikie960ea3f2014-06-08 16:18:35 +00005315bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5316 OperandVector &Operands,
5317 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005318 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005319 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005320 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005321 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005322 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005323
5324 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005325 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005326 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005327 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005328 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005329 case Match_MissingFeature:
5330 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5331 return true;
5332 case Match_InvalidOperand: {
5333 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005334 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005335 if (ErrorInfo >= Operands.size())
5336 return Error(IDLoc, "too few operands for instruction");
5337
Daniel Sanders52da7af2015-11-06 12:11:03 +00005338 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005339 if (ErrorLoc == SMLoc())
5340 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005341 }
5342
5343 return Error(ErrorLoc, "invalid operand for instruction");
5344 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005345 case Match_NonZeroOperandForSync:
Simon Atanasyan478220f2018-05-24 07:36:00 +00005346 return Error(IDLoc,
5347 "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005348 case Match_NonZeroOperandForMTCX:
5349 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005350 case Match_MnemonicFail:
5351 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005352 case Match_RequiresDifferentSrcAndDst:
5353 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005354 case Match_RequiresDifferentOperands:
5355 return Error(IDLoc, "registers must be different");
5356 case Match_RequiresNoZeroRegister:
5357 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005358 case Match_RequiresSameSrcAndDst:
5359 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005360 case Match_NoFCCRegisterForCurrentISA:
5361 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5362 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005363 case Match_Immz:
5364 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005365 case Match_UImm1_0:
5366 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5367 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005368 case Match_UImm2_0:
5369 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5370 "expected 2-bit unsigned immediate");
5371 case Match_UImm2_1:
5372 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5373 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005374 case Match_UImm3_0:
5375 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5376 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005377 case Match_UImm4_0:
5378 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5379 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005380 case Match_SImm4_0:
5381 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5382 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005383 case Match_UImm5_0:
5384 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5385 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005386 case Match_SImm5_0:
5387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5388 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005389 case Match_UImm5_1:
5390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5391 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005392 case Match_UImm5_32:
5393 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5394 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005395 case Match_UImm5_33:
5396 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5397 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005398 case Match_UImm5_0_Report_UImm6:
5399 // This is used on UImm5 operands that have a corresponding UImm5_32
5400 // operand to avoid confusing the user.
5401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5402 "expected 6-bit unsigned immediate");
5403 case Match_UImm5_Lsl2:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005406 case Match_UImmRange2_64:
5407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5408 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005409 case Match_UImm6_0:
5410 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5411 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005412 case Match_UImm6_Lsl2:
5413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5414 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005415 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5417 "expected 6-bit signed immediate");
5418 case Match_UImm7_0:
5419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5420 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005421 case Match_UImm7_N1:
5422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5423 "expected immediate in range -1 .. 126");
5424 case Match_SImm7_Lsl2:
5425 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5426 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005427 case Match_UImm8_0:
5428 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5429 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005430 case Match_UImm10_0:
5431 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5432 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005433 case Match_SImm10_0:
5434 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5435 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005436 case Match_SImm11_0:
5437 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5438 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005439 case Match_UImm16:
5440 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005441 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005442 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5443 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005444 case Match_SImm16:
5445 case Match_SImm16_Relaxed:
5446 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5447 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005448 case Match_SImm19_Lsl2:
5449 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5450 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005451 case Match_UImm20_0:
5452 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5453 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005454 case Match_UImm26_0:
5455 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5456 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005457 case Match_SImm32:
5458 case Match_SImm32_Relaxed:
5459 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5460 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005461 case Match_UImm32_Coerced:
5462 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5463 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005464 case Match_MemSImm9:
5465 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5466 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005467 case Match_MemSImm10:
5468 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5469 "expected memory with 10-bit signed offset");
5470 case Match_MemSImm10Lsl1:
5471 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5472 "expected memory with 11-bit signed offset and multiple of 2");
5473 case Match_MemSImm10Lsl2:
5474 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5475 "expected memory with 12-bit signed offset and multiple of 4");
5476 case Match_MemSImm10Lsl3:
5477 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5478 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005479 case Match_MemSImm11:
5480 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5481 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005482 case Match_MemSImm12:
5483 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5484 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005485 case Match_MemSImm16:
5486 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5487 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005488 case Match_MemSImmPtr:
5489 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5490 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005491 case Match_RequiresPosSizeRange0_32: {
5492 SMLoc ErrorStart = Operands[3]->getStartLoc();
5493 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5494 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5495 SMRange(ErrorStart, ErrorEnd));
5496 }
Simon Dardis55e44672017-09-14 17:27:53 +00005497 case Match_RequiresPosSizeUImm6: {
5498 SMLoc ErrorStart = Operands[3]->getStartLoc();
5499 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5500 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5501 SMRange(ErrorStart, ErrorEnd));
5502 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005503 case Match_RequiresPosSizeRange33_64: {
5504 SMLoc ErrorStart = Operands[3]->getStartLoc();
5505 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5506 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5507 SMRange(ErrorStart, ErrorEnd));
5508 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005509 }
Craig Topper589ceee2015-01-03 08:16:34 +00005510
5511 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005512}
5513
Toma Tabacud9d344b2015-04-27 14:05:04 +00005514void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5515 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5516 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5517 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005518}
5519
Toma Tabacu81496c12015-05-20 08:54:45 +00005520void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5521 if (!AssemblerOptions.back()->isMacro())
5522 Warning(Loc, "macro instruction expanded into multiple instructions");
5523}
5524
Daniel Sandersef638fe2014-10-03 15:37:37 +00005525void
5526MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5527 SMRange Range, bool ShowColors) {
5528 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005529 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005530 ShowColors);
5531}
5532
Jack Carter1ac53222013-02-20 23:11:17 +00005533int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005534 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005535
Vladimir Medic4c299852013-11-06 11:27:05 +00005536 CC = StringSwitch<unsigned>(Name)
5537 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005538 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005539 .Case("a0", 4)
5540 .Case("a1", 5)
5541 .Case("a2", 6)
5542 .Case("a3", 7)
5543 .Case("v0", 2)
5544 .Case("v1", 3)
5545 .Case("s0", 16)
5546 .Case("s1", 17)
5547 .Case("s2", 18)
5548 .Case("s3", 19)
5549 .Case("s4", 20)
5550 .Case("s5", 21)
5551 .Case("s6", 22)
5552 .Case("s7", 23)
5553 .Case("k0", 26)
5554 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005555 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005556 .Case("sp", 29)
5557 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005558 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005559 .Case("ra", 31)
5560 .Case("t0", 8)
5561 .Case("t1", 9)
5562 .Case("t2", 10)
5563 .Case("t3", 11)
5564 .Case("t4", 12)
5565 .Case("t5", 13)
5566 .Case("t6", 14)
5567 .Case("t7", 15)
5568 .Case("t8", 24)
5569 .Case("t9", 25)
5570 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005571
Toma Tabacufda445c2014-09-15 15:33:01 +00005572 if (!(isABI_N32() || isABI_N64()))
5573 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005574
Daniel Sandersef638fe2014-10-03 15:37:37 +00005575 if (12 <= CC && CC <= 15) {
5576 // Name is one of t4-t7
5577 AsmToken RegTok = getLexer().peekTok();
5578 SMRange RegRange = RegTok.getLocRange();
5579
5580 StringRef FixedName = StringSwitch<StringRef>(Name)
5581 .Case("t4", "t0")
5582 .Case("t5", "t1")
5583 .Case("t6", "t2")
5584 .Case("t7", "t3")
5585 .Default("");
5586 assert(FixedName != "" && "Register name is not one of t4-t7.");
5587
5588 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5589 "Did you mean $" + FixedName + "?", RegRange);
5590 }
5591
Toma Tabacufda445c2014-09-15 15:33:01 +00005592 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5593 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5594 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5595 if (8 <= CC && CC <= 11)
5596 CC += 4;
5597
5598 if (CC == -1)
5599 CC = StringSwitch<unsigned>(Name)
5600 .Case("a4", 8)
5601 .Case("a5", 9)
5602 .Case("a6", 10)
5603 .Case("a7", 11)
5604 .Case("kt0", 26)
5605 .Case("kt1", 27)
5606 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005607
5608 return CC;
5609}
Jack Carterd0bd6422013-04-18 00:41:53 +00005610
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005611int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5612 int CC;
5613
5614 CC = StringSwitch<unsigned>(Name)
5615 .Case("hwr_cpunum", 0)
5616 .Case("hwr_synci_step", 1)
5617 .Case("hwr_cc", 2)
5618 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005619 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005620 .Default(-1);
5621
5622 return CC;
5623}
5624
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005625int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005626 if (Name[0] == 'f') {
5627 StringRef NumString = Name.substr(1);
5628 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005629 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005630 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005631 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005632 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005633 return IntVal;
5634 }
5635 return -1;
5636}
Jack Cartera63b16a2012-09-07 00:23:42 +00005637
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005638int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005639 if (Name.startswith("fcc")) {
5640 StringRef NumString = Name.substr(3);
5641 unsigned IntVal;
5642 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005643 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005644 if (IntVal > 7) // There are only 8 fcc registers.
5645 return -1;
5646 return IntVal;
5647 }
5648 return -1;
5649}
5650
5651int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005652 if (Name.startswith("ac")) {
5653 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005654 unsigned IntVal;
5655 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005656 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005657 if (IntVal > 3) // There are only 3 acc registers.
5658 return -1;
5659 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005660 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005661 return -1;
5662}
Jack Carterd0bd6422013-04-18 00:41:53 +00005663
Jack Carter5dc8ac92013-09-25 23:50:44 +00005664int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5665 unsigned IntVal;
5666
5667 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5668 return -1;
5669
5670 if (IntVal > 31)
5671 return -1;
5672
5673 return IntVal;
5674}
5675
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005676int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5677 int CC;
5678
5679 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005680 .Case("msair", 0)
5681 .Case("msacsr", 1)
5682 .Case("msaaccess", 2)
5683 .Case("msasave", 3)
5684 .Case("msamodify", 4)
5685 .Case("msarequest", 5)
5686 .Case("msamap", 6)
5687 .Case("msaunmap", 7)
5688 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005689
5690 return CC;
5691}
5692
Simon Dardis3aa8a902017-02-06 12:43:46 +00005693bool MipsAsmParser::canUseATReg() {
5694 return AssemblerOptions.back()->getATRegIndex() != 0;
5695}
5696
Toma Tabacu89a712b2015-04-15 10:48:56 +00005697unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005698 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005699 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005700 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005701 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005702 return 0;
5703 }
5704 unsigned AT = getReg(
5705 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005706 return AT;
5707}
Jack Carter0b744b32012-10-04 02:29:46 +00005708
Jack Carterd0bd6422013-04-18 00:41:53 +00005709unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005710 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005711}
5712
Toma Tabacu13964452014-09-04 13:23:44 +00005713bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005714 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005715 LLVM_DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005716
Jack Carter30a59822012-10-04 04:03:53 +00005717 // Check if the current operand has a custom associated parser, if so, try to
5718 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005719 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5720 if (ResTy == MatchOperand_Success)
5721 return false;
5722 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5723 // there was a match, but an error occurred, in which case, just return that
5724 // the operand parsing failed.
5725 if (ResTy == MatchOperand_ParseFail)
5726 return true;
5727
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005728 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005729
Jack Carterb4dbc172012-09-05 23:34:03 +00005730 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005731 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005732 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005733 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005734
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005735 // Almost all registers have been parsed by custom parsers. There is only
5736 // one exception to this. $zero (and it's alias $0) will reach this point
5737 // for div, divu, and similar instructions because it is not an operand
5738 // to the instruction definition but an explicit register. Special case
5739 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005740 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005741 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005742
Jack Carterd0bd6422013-04-18 00:41:53 +00005743 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005744 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005745 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005746 return true;
5747
Jack Carter873c7242013-01-12 01:03:14 +00005748 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005749 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005750 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005751 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005752 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005753
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005754 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005755 return false;
5756 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005757 default: {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005758 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005759
5760 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005761 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005762 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005763 return true;
5764
Jack Carter873c7242013-01-12 01:03:14 +00005765 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5766
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005767 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005768 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005769 }
Jack Carter0b744b32012-10-04 02:29:46 +00005770 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005771 return true;
5772}
5773
Jack Carterb5cf5902013-04-17 00:18:04 +00005774bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005775 switch (Expr->getKind()) {
5776 case MCExpr::Constant:
5777 return true;
5778 case MCExpr::SymbolRef:
5779 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005780 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005781 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005782 if (!isEvaluated(BE->getLHS()))
5783 return false;
5784 return isEvaluated(BE->getRHS());
5785 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005786 case MCExpr::Unary:
5787 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005788 case MCExpr::Target:
5789 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005790 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005791 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005792}
Jack Carterd0bd6422013-04-18 00:41:53 +00005793
Jack Carterb4dbc172012-09-05 23:34:03 +00005794bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5795 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005796 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005797 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005798 if (ResTy == MatchOperand_Success) {
5799 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005800 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005801 StartLoc = Operand.getStartLoc();
5802 EndLoc = Operand.getEndLoc();
5803
5804 // AFAIK, we only support numeric registers and named GPR's in CFI
5805 // directives.
5806 // Don't worry about eating tokens before failing. Using an unrecognised
5807 // register is a parse error.
5808 if (Operand.isGPRAsmReg()) {
5809 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005810 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005811 }
5812
5813 return (RegNo == (unsigned)-1);
5814 }
5815
5816 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005817 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005818}
5819
Jack Carterb5cf5902013-04-17 00:18:04 +00005820bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005821 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005822
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005823 if (isParenExpr)
5824 return getParser().parseParenExprOfDepth(0, Res, S);
5825 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005826}
5827
Alex Bradbury58eba092016-11-01 16:32:05 +00005828OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005829MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005830 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005831 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005832 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005833 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005834 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005835 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005836 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005837 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005838
Jack Carterb5cf5902013-04-17 00:18:04 +00005839 if (getLexer().getKind() == AsmToken::LParen) {
5840 Parser.Lex();
5841 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005842 }
5843
Jack Carterb5cf5902013-04-17 00:18:04 +00005844 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005845 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005846 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005847
Jack Carterd0bd6422013-04-18 00:41:53 +00005848 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005849 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005850 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005851 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005852 SMLoc E =
5853 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005854 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005855 return MatchOperand_Success;
5856 }
5857 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005858 SMLoc E =
5859 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005860
Jack Carterd0bd6422013-04-18 00:41:53 +00005861 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005862 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005863 auto Base = MipsOperand::createGPRReg(
5864 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005865 Operands.push_back(
5866 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005867 return MatchOperand_Success;
5868 }
Simon Dardis858915f2016-10-18 15:17:17 +00005869 MCBinaryExpr::Opcode Opcode;
5870 // GAS and LLVM treat comparison operators different. GAS will generate -1
5871 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5872 // highly unlikely to be found in a memory offset expression, we don't
5873 // handle them.
5874 switch (Tok.getKind()) {
5875 case AsmToken::Plus:
5876 Opcode = MCBinaryExpr::Add;
5877 Parser.Lex();
5878 break;
5879 case AsmToken::Minus:
5880 Opcode = MCBinaryExpr::Sub;
5881 Parser.Lex();
5882 break;
5883 case AsmToken::Star:
5884 Opcode = MCBinaryExpr::Mul;
5885 Parser.Lex();
5886 break;
5887 case AsmToken::Pipe:
5888 Opcode = MCBinaryExpr::Or;
5889 Parser.Lex();
5890 break;
5891 case AsmToken::Amp:
5892 Opcode = MCBinaryExpr::And;
5893 Parser.Lex();
5894 break;
5895 case AsmToken::LessLess:
5896 Opcode = MCBinaryExpr::Shl;
5897 Parser.Lex();
5898 break;
5899 case AsmToken::GreaterGreater:
5900 Opcode = MCBinaryExpr::LShr;
5901 Parser.Lex();
5902 break;
5903 case AsmToken::Caret:
5904 Opcode = MCBinaryExpr::Xor;
5905 Parser.Lex();
5906 break;
5907 case AsmToken::Slash:
5908 Opcode = MCBinaryExpr::Div;
5909 Parser.Lex();
5910 break;
5911 case AsmToken::Percent:
5912 Opcode = MCBinaryExpr::Mod;
5913 Parser.Lex();
5914 break;
5915 default:
5916 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5917 return MatchOperand_ParseFail;
5918 }
5919 const MCExpr * NextExpr;
5920 if (getParser().parseExpression(NextExpr))
5921 return MatchOperand_ParseFail;
5922 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005923 }
5924
Jack Carterd0bd6422013-04-18 00:41:53 +00005925 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005926 }
5927
Toma Tabacu13964452014-09-04 13:23:44 +00005928 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005929 if (Res != MatchOperand_Success)
5930 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005931
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005932 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005933 Error(Parser.getTok().getLoc(), "')' expected");
5934 return MatchOperand_ParseFail;
5935 }
5936
Jack Carter873c7242013-01-12 01:03:14 +00005937 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5938
Jack Carterd0bd6422013-04-18 00:41:53 +00005939 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005940
Craig Topper062a2ba2014-04-25 05:30:21 +00005941 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005942 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005943
Jack Carterd0bd6422013-04-18 00:41:53 +00005944 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005945 std::unique_ptr<MipsOperand> op(
5946 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005947 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005948 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005949 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005950 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005951 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5952 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005953 if (IdVal->evaluateAsAbsolute(Imm))
5954 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005955 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005956 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005957 getContext());
5958 }
5959
David Blaikie960ea3f2014-06-08 16:18:35 +00005960 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005961 return MatchOperand_Success;
5962}
5963
David Blaikie960ea3f2014-06-08 16:18:35 +00005964bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005965 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005966 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005967 if (Sym) {
5968 SMLoc S = Parser.getTok().getLoc();
5969 const MCExpr *Expr;
5970 if (Sym->isVariable())
5971 Expr = Sym->getVariableValue();
5972 else
5973 return false;
5974 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005975 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005976 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005977 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005978 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005979 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005980 if (ResTy == MatchOperand_Success) {
5981 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005982 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005983 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005984 llvm_unreachable("Should never ParseFail");
5985 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005986 }
Jack Carterd76b2372013-03-21 21:44:16 +00005987 }
5988 }
5989 return false;
5990}
Jack Carterd0bd6422013-04-18 00:41:53 +00005991
Alex Bradbury58eba092016-11-01 16:32:05 +00005992OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005993MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005994 StringRef Identifier,
5995 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005996 int Index = matchCPURegisterName(Identifier);
5997 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005998 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005999 Index, Identifier, getContext().getRegisterInfo(), S,
6000 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006001 return MatchOperand_Success;
6002 }
6003
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006004 Index = matchHWRegsRegisterName(Identifier);
6005 if (Index != -1) {
6006 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006007 Index, Identifier, getContext().getRegisterInfo(), S,
6008 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006009 return MatchOperand_Success;
6010 }
6011
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006012 Index = matchFPURegisterName(Identifier);
6013 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006014 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006015 Index, Identifier, getContext().getRegisterInfo(), S,
6016 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006017 return MatchOperand_Success;
6018 }
6019
6020 Index = matchFCCRegisterName(Identifier);
6021 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006022 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006023 Index, Identifier, getContext().getRegisterInfo(), S,
6024 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006025 return MatchOperand_Success;
6026 }
6027
6028 Index = matchACRegisterName(Identifier);
6029 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006030 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006031 Index, Identifier, getContext().getRegisterInfo(), S,
6032 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006033 return MatchOperand_Success;
6034 }
6035
6036 Index = matchMSA128RegisterName(Identifier);
6037 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006038 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006039 Index, Identifier, getContext().getRegisterInfo(), S,
6040 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006041 return MatchOperand_Success;
6042 }
6043
6044 Index = matchMSA128CtrlRegisterName(Identifier);
6045 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006046 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006047 Index, Identifier, getContext().getRegisterInfo(), S,
6048 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006049 return MatchOperand_Success;
6050 }
6051
6052 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006053}
6054
Alex Bradbury58eba092016-11-01 16:32:05 +00006055OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006056MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006057 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00006058 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006059
6060 if (Token.is(AsmToken::Identifier)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006061 LLVM_DEBUG(dbgs() << ".. identifier\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006062 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006063 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006064 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006065 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006066 } else if (Token.is(AsmToken::Integer)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006067 LLVM_DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006068 int64_t RegNum = Token.getIntVal();
6069 if (RegNum < 0 || RegNum > 31) {
6070 // Show the error, but treat invalid register
6071 // number as a normal one to continue parsing
6072 // and catch other possible errors.
6073 Error(getLexer().getLoc(), "invalid register number");
6074 }
Toma Tabacu13964452014-09-04 13:23:44 +00006075 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006076 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006077 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006078 return MatchOperand_Success;
6079 }
6080
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006081 LLVM_DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006082
6083 return MatchOperand_NoMatch;
6084}
6085
Alex Bradbury58eba092016-11-01 16:32:05 +00006086OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006087MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006088 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006089 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006090
6091 auto Token = Parser.getTok();
6092
6093 SMLoc S = Token.getLoc();
6094
6095 if (Token.isNot(AsmToken::Dollar)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006096 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006097 if (Token.is(AsmToken::Identifier)) {
6098 if (searchSymbolAlias(Operands))
6099 return MatchOperand_Success;
6100 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006101 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006102 return MatchOperand_NoMatch;
6103 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006104 LLVM_DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006105
Toma Tabacu13964452014-09-04 13:23:44 +00006106 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006107 if (ResTy == MatchOperand_Success) {
6108 Parser.Lex(); // $
6109 Parser.Lex(); // identifier
6110 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006111 return ResTy;
6112}
6113
Alex Bradbury58eba092016-11-01 16:32:05 +00006114OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006115MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006116 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006117 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006118
6119 SMLoc S = getLexer().getLoc();
6120
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006121 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006122 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006123 if (ResTy != MatchOperand_NoMatch)
6124 return ResTy;
6125
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006126 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006127 const MCExpr *Expr = nullptr;
6128 if (Parser.parseExpression(Expr)) {
6129 // We have no way of knowing if a symbol was consumed so we must ParseFail
6130 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006131 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006132 Operands.push_back(
6133 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006134 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006135}
6136
Alex Bradbury58eba092016-11-01 16:32:05 +00006137OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006138MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006139 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006140 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006141 // If the first token is '$' we may have register operand. We have to reject
6142 // cases where it is not a register. Complicating the matter is that
6143 // register names are not reserved across all ABIs.
6144 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006145 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006146 if (Parser.getTok().is(AsmToken::Dollar)) {
6147 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6148 ? MatchOperand_ParseFail
6149 : MatchOperand_NoMatch;
6150 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006151 if (getParser().parseExpression(IdVal))
6152 return MatchOperand_ParseFail;
6153 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006154 if (!MCE)
6155 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006156 int64_t Val = MCE->getValue();
6157 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6158 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006159 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006160 return MatchOperand_Success;
6161}
6162
Alex Bradbury58eba092016-11-01 16:32:05 +00006163OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006164MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6165 MCAsmParser &Parser = getParser();
6166 SmallVector<unsigned, 10> Regs;
6167 unsigned RegNo;
6168 unsigned PrevReg = Mips::NoRegister;
6169 bool RegRange = false;
6170 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6171
6172 if (Parser.getTok().isNot(AsmToken::Dollar))
6173 return MatchOperand_ParseFail;
6174
6175 SMLoc S = Parser.getTok().getLoc();
6176 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6177 SMLoc E = getLexer().getLoc();
6178 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6179 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6180 if (RegRange) {
6181 // Remove last register operand because registers from register range
6182 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006183 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6184 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006185 Regs.push_back(RegNo);
6186 } else {
6187 unsigned TmpReg = PrevReg + 1;
6188 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006189 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6190 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6191 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006192 Error(E, "invalid register operand");
6193 return MatchOperand_ParseFail;
6194 }
6195
6196 PrevReg = TmpReg;
6197 Regs.push_back(TmpReg++);
6198 }
6199 }
6200
6201 RegRange = false;
6202 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006203 if ((PrevReg == Mips::NoRegister) &&
6204 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6205 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006206 Error(E, "$16 or $31 expected");
6207 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006208 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6209 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6210 !isGP64bit()) ||
6211 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6212 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6213 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006214 Error(E, "invalid register operand");
6215 return MatchOperand_ParseFail;
6216 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006217 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6218 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6219 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006220 Error(E, "consecutive register numbers expected");
6221 return MatchOperand_ParseFail;
6222 }
6223
6224 Regs.push_back(RegNo);
6225 }
6226
6227 if (Parser.getTok().is(AsmToken::Minus))
6228 RegRange = true;
6229
6230 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6231 !Parser.getTok().isNot(AsmToken::Comma)) {
6232 Error(E, "',' or '-' expected");
6233 return MatchOperand_ParseFail;
6234 }
6235
6236 Lex(); // Consume comma or minus
6237 if (Parser.getTok().isNot(AsmToken::Dollar))
6238 break;
6239
6240 PrevReg = RegNo;
6241 }
6242
6243 SMLoc E = Parser.getTok().getLoc();
6244 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6245 parseMemOperand(Operands);
6246 return MatchOperand_Success;
6247}
6248
Alex Bradbury58eba092016-11-01 16:32:05 +00006249OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006250MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6251 MCAsmParser &Parser = getParser();
6252
6253 SMLoc S = Parser.getTok().getLoc();
6254 if (parseAnyRegister(Operands) != MatchOperand_Success)
6255 return MatchOperand_ParseFail;
6256
6257 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006258 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006259
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006260 Operands.pop_back();
6261 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006262 return MatchOperand_Success;
6263}
6264
Alex Bradbury58eba092016-11-01 16:32:05 +00006265OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006266MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6267 MCAsmParser &Parser = getParser();
6268 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6269 SmallVector<unsigned, 10> Regs;
6270
6271 if (Parser.getTok().isNot(AsmToken::Dollar))
6272 return MatchOperand_ParseFail;
6273
6274 SMLoc S = Parser.getTok().getLoc();
6275
6276 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6277 return MatchOperand_ParseFail;
6278
6279 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6280 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6281 Regs.push_back(RegNo);
6282
6283 SMLoc E = Parser.getTok().getLoc();
6284 if (Parser.getTok().isNot(AsmToken::Comma)) {
6285 Error(E, "',' expected");
6286 return MatchOperand_ParseFail;
6287 }
6288
6289 // Remove comma.
6290 Parser.Lex();
6291
6292 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6293 return MatchOperand_ParseFail;
6294
6295 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6296 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6297 Regs.push_back(RegNo);
6298
6299 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6300
6301 return MatchOperand_Success;
6302}
6303
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006304/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6305/// either this.
6306/// ::= '(', register, ')'
6307/// handle it before we iterate so we don't get tripped up by the lack of
6308/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006309bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006310 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006311 if (getLexer().is(AsmToken::LParen)) {
6312 Operands.push_back(
6313 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6314 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006315 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006316 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006317 return Error(Loc, "unexpected token in argument list");
6318 }
6319 if (Parser.getTok().isNot(AsmToken::RParen)) {
6320 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006321 return Error(Loc, "unexpected token, expected ')'");
6322 }
6323 Operands.push_back(
6324 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6325 Parser.Lex();
6326 }
6327 return false;
6328}
6329
6330/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6331/// either one of these.
6332/// ::= '[', register, ']'
6333/// ::= '[', integer, ']'
6334/// handle it before we iterate so we don't get tripped up by the lack of
6335/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006336bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006337 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006338 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006339 if (getLexer().is(AsmToken::LBrac)) {
6340 Operands.push_back(
6341 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6342 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006343 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006344 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006345 return Error(Loc, "unexpected token in argument list");
6346 }
6347 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6348 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006349 return Error(Loc, "unexpected token, expected ']'");
6350 }
6351 Operands.push_back(
6352 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6353 Parser.Lex();
6354 }
6355 return false;
6356}
6357
David Blaikie960ea3f2014-06-08 16:18:35 +00006358bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6359 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006360 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006361 LLVM_DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006362
6363 // We have reached first instruction, module directive are now forbidden.
6364 getTargetStreamer().forbidModuleDirective();
6365
Vladimir Medic74593e62013-07-17 15:00:42 +00006366 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006367 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006368 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006369 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006370 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006371 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006372
6373 // Read the remaining operands.
6374 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6375 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006376 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006377 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006378 return Error(Loc, "unexpected token in argument list");
6379 }
Toma Tabacu13964452014-09-04 13:23:44 +00006380 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006381 return true;
6382 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006383
Jack Carterd0bd6422013-04-18 00:41:53 +00006384 while (getLexer().is(AsmToken::Comma)) {
6385 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006386 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006387 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006388 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006389 return Error(Loc, "unexpected token in argument list");
6390 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006391 // Parse bracket and parenthesis suffixes before we iterate
6392 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006393 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006394 return true;
6395 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006396 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006397 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006398 }
6399 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006400 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6401 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006402 return Error(Loc, "unexpected token in argument list");
6403 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006404 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006405 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006406}
6407
Nirav Dave996fc132016-05-05 14:15:46 +00006408// FIXME: Given that these have the same name, these should both be
6409// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006410bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006411 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006412 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006413}
6414
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006415bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006416 return Error(Loc, ErrorMsg);
6417}
6418
Jack Carter0b744b32012-10-04 02:29:46 +00006419bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006420 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006421 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006422
6423 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006424 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006425
6426 Parser.Lex(); // Eat "noat".
6427
Jack Carterd0bd6422013-04-18 00:41:53 +00006428 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006429 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006430 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006431 return false;
6432 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006433
6434 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006435 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006436 return false;
6437}
Jack Carterd0bd6422013-04-18 00:41:53 +00006438
Jack Carter0b744b32012-10-04 02:29:46 +00006439bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006440 // Line can be: ".set at", which sets $at to $1
6441 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006442 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006443 Parser.Lex(); // Eat "at".
6444
Jack Carter0b744b32012-10-04 02:29:46 +00006445 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006446 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006447 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006448
6449 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006450 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006451 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006452 }
6453
6454 if (getLexer().isNot(AsmToken::Equal)) {
6455 reportParseError("unexpected token, expected equals sign");
6456 return false;
6457 }
6458 Parser.Lex(); // Eat "=".
6459
6460 if (getLexer().isNot(AsmToken::Dollar)) {
6461 if (getLexer().is(AsmToken::EndOfStatement)) {
6462 reportParseError("no register specified");
6463 return false;
6464 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006465 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006466 return false;
6467 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006468 }
6469 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006470
Toma Tabacu16a74492015-02-13 10:30:57 +00006471 // Find out what "reg" is.
6472 unsigned AtRegNo;
6473 const AsmToken &Reg = Parser.getTok();
6474 if (Reg.is(AsmToken::Identifier)) {
6475 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6476 } else if (Reg.is(AsmToken::Integer)) {
6477 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006478 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006479 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006480 return false;
6481 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006482
6483 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006484 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006485 reportParseError("invalid register");
6486 return false;
6487 }
6488 Parser.Lex(); // Eat "reg".
6489
6490 // If this is not the end of the statement, report an error.
6491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6492 reportParseError("unexpected token, expected end of statement");
6493 return false;
6494 }
6495
6496 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6497
6498 Parser.Lex(); // Consume the EndOfStatement.
6499 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006500}
6501
6502bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006503 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006504 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006505 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006507 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006508 return false;
6509 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006510 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006511 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006512 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006513 return false;
6514}
6515
6516bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006517 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006518 Parser.Lex();
6519 // If this is not the end of the statement, report an error.
6520 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006521 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006522 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006523 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006524 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006525 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006526 Parser.Lex(); // Consume the EndOfStatement.
6527 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006528}
6529
6530bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006531 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006532 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006533 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006534 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006535 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006536 return false;
6537 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006538 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006539 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006540 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006541 return false;
6542}
6543
6544bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006545 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006546 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006547 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006549 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006550 return false;
6551 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006552 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006553 reportParseError("`noreorder' must be set before `nomacro'");
6554 return false;
6555 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006556 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006557 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006558 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006559 return false;
6560}
Jack Carterd76b2372013-03-21 21:44:16 +00006561
Daniel Sanders44934432014-08-07 12:03:36 +00006562bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006563 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006564 Parser.Lex();
6565
6566 // If this is not the end of the statement, report an error.
6567 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006568 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006569
6570 setFeatureBits(Mips::FeatureMSA, "msa");
6571 getTargetStreamer().emitDirectiveSetMsa();
6572 return false;
6573}
6574
6575bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006576 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006577 Parser.Lex();
6578
6579 // If this is not the end of the statement, report an error.
6580 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006581 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006582
6583 clearFeatureBits(Mips::FeatureMSA, "msa");
6584 getTargetStreamer().emitDirectiveSetNoMsa();
6585 return false;
6586}
6587
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006588bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006589 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006590 Parser.Lex(); // Eat "nodsp".
6591
6592 // If this is not the end of the statement, report an error.
6593 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6594 reportParseError("unexpected token, expected end of statement");
6595 return false;
6596 }
6597
6598 clearFeatureBits(Mips::FeatureDSP, "dsp");
6599 getTargetStreamer().emitDirectiveSetNoDsp();
6600 return false;
6601}
6602
Toma Tabacucc2502d2014-11-04 17:18:07 +00006603bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006604 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006605 Parser.Lex(); // Eat "mips16".
6606
Jack Carter39536722014-01-22 23:08:42 +00006607 // If this is not the end of the statement, report an error.
6608 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006609 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006610 return false;
6611 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006612
6613 setFeatureBits(Mips::FeatureMips16, "mips16");
6614 getTargetStreamer().emitDirectiveSetMips16();
6615 Parser.Lex(); // Consume the EndOfStatement.
6616 return false;
6617}
6618
6619bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006620 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006621 Parser.Lex(); // Eat "nomips16".
6622
6623 // If this is not the end of the statement, report an error.
6624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6625 reportParseError("unexpected token, expected end of statement");
6626 return false;
6627 }
6628
6629 clearFeatureBits(Mips::FeatureMips16, "mips16");
6630 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006631 Parser.Lex(); // Consume the EndOfStatement.
6632 return false;
6633}
6634
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006635bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006636 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006637 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006638 // Line can be: .set fp=32
6639 // .set fp=xx
6640 // .set fp=64
6641 Parser.Lex(); // Eat fp token
6642 AsmToken Tok = Parser.getTok();
6643 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006644 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006645 return false;
6646 }
6647 Parser.Lex(); // Eat '=' token.
6648 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006649
6650 if (!parseFpABIValue(FpAbiVal, ".set"))
6651 return false;
6652
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006653 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006654 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006655 return false;
6656 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006657 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006658 Parser.Lex(); // Consume the EndOfStatement.
6659 return false;
6660}
6661
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006662bool MipsAsmParser::parseSetOddSPRegDirective() {
6663 MCAsmParser &Parser = getParser();
6664
6665 Parser.Lex(); // Eat "oddspreg".
6666 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6667 reportParseError("unexpected token, expected end of statement");
6668 return false;
6669 }
6670
6671 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6672 getTargetStreamer().emitDirectiveSetOddSPReg();
6673 return false;
6674}
6675
6676bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6677 MCAsmParser &Parser = getParser();
6678
6679 Parser.Lex(); // Eat "nooddspreg".
6680 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6681 reportParseError("unexpected token, expected end of statement");
6682 return false;
6683 }
6684
6685 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6686 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6687 return false;
6688}
6689
Simon Dardis805f1e02017-07-11 21:28:36 +00006690bool MipsAsmParser::parseSetMtDirective() {
6691 MCAsmParser &Parser = getParser();
6692 Parser.Lex(); // Eat "mt".
6693
6694 // If this is not the end of the statement, report an error.
6695 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6696 reportParseError("unexpected token, expected end of statement");
6697 return false;
6698 }
6699
6700 setFeatureBits(Mips::FeatureMT, "mt");
6701 getTargetStreamer().emitDirectiveSetMt();
6702 Parser.Lex(); // Consume the EndOfStatement.
6703 return false;
6704}
6705
6706bool MipsAsmParser::parseSetNoMtDirective() {
6707 MCAsmParser &Parser = getParser();
6708 Parser.Lex(); // Eat "nomt".
6709
6710 // If this is not the end of the statement, report an error.
6711 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6712 reportParseError("unexpected token, expected end of statement");
6713 return false;
6714 }
6715
6716 clearFeatureBits(Mips::FeatureMT, "mt");
6717
6718 getTargetStreamer().emitDirectiveSetNoMt();
6719 Parser.Lex(); // Consume the EndOfStatement.
6720 return false;
6721}
6722
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006723bool MipsAsmParser::parseSetNoCRCDirective() {
6724 MCAsmParser &Parser = getParser();
6725 Parser.Lex(); // Eat "nocrc".
6726
6727 // If this is not the end of the statement, report an error.
6728 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6729 reportParseError("unexpected token, expected end of statement");
6730 return false;
6731 }
6732
6733 clearFeatureBits(Mips::FeatureCRC, "crc");
6734
6735 getTargetStreamer().emitDirectiveSetNoCRC();
6736 Parser.Lex(); // Consume the EndOfStatement.
6737 return false;
6738}
6739
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006740bool MipsAsmParser::parseSetNoVirtDirective() {
6741 MCAsmParser &Parser = getParser();
6742 Parser.Lex(); // Eat "novirt".
6743
6744 // If this is not the end of the statement, report an error.
6745 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6746 reportParseError("unexpected token, expected end of statement");
6747 return false;
6748 }
6749
6750 clearFeatureBits(Mips::FeatureVirt, "virt");
6751
6752 getTargetStreamer().emitDirectiveSetNoVirt();
6753 Parser.Lex(); // Consume the EndOfStatement.
6754 return false;
6755}
6756
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006757bool MipsAsmParser::parseSetNoGINVDirective() {
6758 MCAsmParser &Parser = getParser();
6759 Parser.Lex(); // Eat "noginv".
6760
6761 // If this is not the end of the statement, report an error.
6762 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6763 reportParseError("unexpected token, expected end of statement");
6764 return false;
6765 }
6766
6767 clearFeatureBits(Mips::FeatureGINV, "ginv");
6768
6769 getTargetStreamer().emitDirectiveSetNoGINV();
6770 Parser.Lex(); // Consume the EndOfStatement.
6771 return false;
6772}
6773
Toma Tabacu9db22db2014-09-09 10:15:38 +00006774bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006775 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006776 SMLoc Loc = getLexer().getLoc();
6777
6778 Parser.Lex();
6779 if (getLexer().isNot(AsmToken::EndOfStatement))
6780 return reportParseError("unexpected token, expected end of statement");
6781
6782 // Always keep an element on the options "stack" to prevent the user
6783 // from changing the initial options. This is how we remember them.
6784 if (AssemblerOptions.size() == 2)
6785 return reportParseError(Loc, ".set pop with no .set push");
6786
Akira Hatanakab11ef082015-11-14 06:35:56 +00006787 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006788 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006789 setAvailableFeatures(
6790 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6791 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006792
6793 getTargetStreamer().emitDirectiveSetPop();
6794 return false;
6795}
6796
6797bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006798 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006799 Parser.Lex();
6800 if (getLexer().isNot(AsmToken::EndOfStatement))
6801 return reportParseError("unexpected token, expected end of statement");
6802
6803 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006804 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006805 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006806
6807 getTargetStreamer().emitDirectiveSetPush();
6808 return false;
6809}
6810
Toma Tabacu29696502015-06-02 09:48:04 +00006811bool MipsAsmParser::parseSetSoftFloatDirective() {
6812 MCAsmParser &Parser = getParser();
6813 Parser.Lex();
6814 if (getLexer().isNot(AsmToken::EndOfStatement))
6815 return reportParseError("unexpected token, expected end of statement");
6816
6817 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6818 getTargetStreamer().emitDirectiveSetSoftFloat();
6819 return false;
6820}
6821
6822bool MipsAsmParser::parseSetHardFloatDirective() {
6823 MCAsmParser &Parser = getParser();
6824 Parser.Lex();
6825 if (getLexer().isNot(AsmToken::EndOfStatement))
6826 return reportParseError("unexpected token, expected end of statement");
6827
6828 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6829 getTargetStreamer().emitDirectiveSetHardFloat();
6830 return false;
6831}
6832
Jack Carterd76b2372013-03-21 21:44:16 +00006833bool MipsAsmParser::parseSetAssignment() {
6834 StringRef Name;
6835 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006836 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006837
6838 if (Parser.parseIdentifier(Name))
6839 reportParseError("expected identifier after .set");
6840
6841 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006842 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006843 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006844
Jack Carter3b2c96e2014-01-22 23:31:38 +00006845 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006846 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006847
Jim Grosbach6f482002015-05-18 18:43:14 +00006848 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006849 Sym->setVariableValue(Value);
6850
6851 return false;
6852}
Jack Carterd0bd6422013-04-18 00:41:53 +00006853
Toma Tabacu26647792014-09-09 12:52:14 +00006854bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006855 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006856 Parser.Lex();
6857 if (getLexer().isNot(AsmToken::EndOfStatement))
6858 return reportParseError("unexpected token, expected end of statement");
6859
6860 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006861 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006862 setAvailableFeatures(
6863 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6864 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006865 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6866
6867 getTargetStreamer().emitDirectiveSetMips0();
6868 return false;
6869}
6870
Toma Tabacu85618b32014-08-19 14:22:52 +00006871bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006872 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006873 Parser.Lex();
6874 if (getLexer().isNot(AsmToken::Equal))
6875 return reportParseError("unexpected token, expected equals sign");
6876
6877 Parser.Lex();
6878 StringRef Arch;
6879 if (Parser.parseIdentifier(Arch))
6880 return reportParseError("expected arch identifier");
6881
6882 StringRef ArchFeatureName =
6883 StringSwitch<StringRef>(Arch)
6884 .Case("mips1", "mips1")
6885 .Case("mips2", "mips2")
6886 .Case("mips3", "mips3")
6887 .Case("mips4", "mips4")
6888 .Case("mips5", "mips5")
6889 .Case("mips32", "mips32")
6890 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006891 .Case("mips32r3", "mips32r3")
6892 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006893 .Case("mips32r6", "mips32r6")
6894 .Case("mips64", "mips64")
6895 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006896 .Case("mips64r3", "mips64r3")
6897 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006898 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006899 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006900 .Case("r4000", "mips3") // This is an implementation of Mips3.
6901 .Default("");
6902
6903 if (ArchFeatureName.empty())
6904 return reportParseError("unsupported architecture");
6905
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006906 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6907 return reportParseError("mips64r6 does not support microMIPS");
6908
Toma Tabacu85618b32014-08-19 14:22:52 +00006909 selectArch(ArchFeatureName);
6910 getTargetStreamer().emitDirectiveSetArch(Arch);
6911 return false;
6912}
6913
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006914bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006915 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006916 Parser.Lex();
6917 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006918 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006919
Matheus Almeida2852af82014-04-22 10:15:54 +00006920 switch (Feature) {
6921 default:
6922 llvm_unreachable("Unimplemented feature");
6923 case Mips::FeatureDSP:
6924 setFeatureBits(Mips::FeatureDSP, "dsp");
6925 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006926 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006927 case Mips::FeatureDSPR2:
6928 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6929 getTargetStreamer().emitDirectiveSetDspr2();
6930 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006931 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006932 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006933 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006934 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006935 case Mips::FeatureMips1:
6936 selectArch("mips1");
6937 getTargetStreamer().emitDirectiveSetMips1();
6938 break;
6939 case Mips::FeatureMips2:
6940 selectArch("mips2");
6941 getTargetStreamer().emitDirectiveSetMips2();
6942 break;
6943 case Mips::FeatureMips3:
6944 selectArch("mips3");
6945 getTargetStreamer().emitDirectiveSetMips3();
6946 break;
6947 case Mips::FeatureMips4:
6948 selectArch("mips4");
6949 getTargetStreamer().emitDirectiveSetMips4();
6950 break;
6951 case Mips::FeatureMips5:
6952 selectArch("mips5");
6953 getTargetStreamer().emitDirectiveSetMips5();
6954 break;
6955 case Mips::FeatureMips32:
6956 selectArch("mips32");
6957 getTargetStreamer().emitDirectiveSetMips32();
6958 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006959 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006960 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006961 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006962 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006963 case Mips::FeatureMips32r3:
6964 selectArch("mips32r3");
6965 getTargetStreamer().emitDirectiveSetMips32R3();
6966 break;
6967 case Mips::FeatureMips32r5:
6968 selectArch("mips32r5");
6969 getTargetStreamer().emitDirectiveSetMips32R5();
6970 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006971 case Mips::FeatureMips32r6:
6972 selectArch("mips32r6");
6973 getTargetStreamer().emitDirectiveSetMips32R6();
6974 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006975 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006976 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006977 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006978 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006979 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006980 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006981 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006982 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006983 case Mips::FeatureMips64r3:
6984 selectArch("mips64r3");
6985 getTargetStreamer().emitDirectiveSetMips64R3();
6986 break;
6987 case Mips::FeatureMips64r5:
6988 selectArch("mips64r5");
6989 getTargetStreamer().emitDirectiveSetMips64R5();
6990 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006991 case Mips::FeatureMips64r6:
6992 selectArch("mips64r6");
6993 getTargetStreamer().emitDirectiveSetMips64R6();
6994 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006995 case Mips::FeatureCRC:
6996 setFeatureBits(Mips::FeatureCRC, "crc");
6997 getTargetStreamer().emitDirectiveSetCRC();
6998 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006999 case Mips::FeatureVirt:
7000 setFeatureBits(Mips::FeatureVirt, "virt");
7001 getTargetStreamer().emitDirectiveSetVirt();
7002 break;
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007003 case Mips::FeatureGINV:
7004 setFeatureBits(Mips::FeatureGINV, "ginv");
7005 getTargetStreamer().emitDirectiveSetGINV();
7006 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00007007 }
7008 return false;
7009}
7010
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007011bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007012 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007013 if (getLexer().isNot(AsmToken::Comma)) {
7014 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007015 return Error(Loc, ErrorStr);
7016 }
7017
Matheus Almeida2852af82014-04-22 10:15:54 +00007018 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007019 return true;
7020}
7021
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007022// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
7023// In this class, it is only used for .cprestore.
7024// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
7025// MipsTargetELFStreamer and MipsAsmParser.
7026bool MipsAsmParser::isPicAndNotNxxAbi() {
7027 return inPicMode() && !(isABI_N32() || isABI_N64());
7028}
7029
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007030bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00007031 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00007032 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007033
Toma Tabacudde4c462014-11-06 10:02:45 +00007034 if (inMips16Mode()) {
7035 reportParseError(".cpload is not supported in Mips16 mode");
7036 return false;
7037 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007038
David Blaikie960ea3f2014-06-08 16:18:35 +00007039 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007040 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007041 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7042 reportParseError("expected register containing function address");
7043 return false;
7044 }
7045
David Blaikie960ea3f2014-06-08 16:18:35 +00007046 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7047 if (!RegOpnd.isGPRAsmReg()) {
7048 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007049 return false;
7050 }
7051
Toma Tabacudde4c462014-11-06 10:02:45 +00007052 // If this is not the end of the statement, report an error.
7053 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7054 reportParseError("unexpected token, expected end of statement");
7055 return false;
7056 }
7057
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007058 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007059 return false;
7060}
7061
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007062bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7063 MCAsmParser &Parser = getParser();
7064
7065 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7066 // is used in non-PIC mode.
7067
7068 if (inMips16Mode()) {
7069 reportParseError(".cprestore is not supported in Mips16 mode");
7070 return false;
7071 }
7072
7073 // Get the stack offset value.
7074 const MCExpr *StackOffset;
7075 int64_t StackOffsetVal;
7076 if (Parser.parseExpression(StackOffset)) {
7077 reportParseError("expected stack offset value");
7078 return false;
7079 }
7080
7081 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7082 reportParseError("stack offset is not an absolute expression");
7083 return false;
7084 }
7085
7086 if (StackOffsetVal < 0) {
7087 Warning(Loc, ".cprestore with negative stack offset has no effect");
7088 IsCpRestoreSet = false;
7089 } else {
7090 IsCpRestoreSet = true;
7091 CpRestoreOffset = StackOffsetVal;
7092 }
7093
7094 // If this is not the end of the statement, report an error.
7095 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7096 reportParseError("unexpected token, expected end of statement");
7097 return false;
7098 }
7099
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007100 if (!getTargetStreamer().emitDirectiveCpRestore(
7101 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007102 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007103 Parser.Lex(); // Consume the EndOfStatement.
7104 return false;
7105}
7106
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007107bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007108 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007109 unsigned FuncReg;
7110 unsigned Save;
7111 bool SaveIsReg = true;
7112
Matheus Almeida7e815762014-06-18 13:08:59 +00007113 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007114 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007115 if (ResTy == MatchOperand_NoMatch) {
7116 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007117 return false;
7118 }
7119
7120 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7121 if (!FuncRegOpnd.isGPRAsmReg()) {
7122 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007123 return false;
7124 }
7125
7126 FuncReg = FuncRegOpnd.getGPR32Reg();
7127 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007128
Toma Tabacu65f10572014-09-16 15:00:52 +00007129 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007130 return true;
7131
Toma Tabacu13964452014-09-04 13:23:44 +00007132 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007133 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007134 const MCExpr *OffsetExpr;
7135 int64_t OffsetVal;
7136 SMLoc ExprLoc = getLexer().getLoc();
7137
7138 if (Parser.parseExpression(OffsetExpr) ||
7139 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7140 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007141 return false;
7142 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007143
7144 Save = OffsetVal;
7145 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007146 } else {
7147 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7148 if (!SaveOpnd.isGPRAsmReg()) {
7149 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007150 return false;
7151 }
7152 Save = SaveOpnd.getGPR32Reg();
7153 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007154
Toma Tabacu65f10572014-09-16 15:00:52 +00007155 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007156 return true;
7157
Toma Tabacu8874eac2015-02-18 13:46:53 +00007158 const MCExpr *Expr;
7159 if (Parser.parseExpression(Expr)) {
7160 reportParseError("expected expression");
7161 return false;
7162 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007163
Toma Tabacu8874eac2015-02-18 13:46:53 +00007164 if (Expr->getKind() != MCExpr::SymbolRef) {
7165 reportParseError("expected symbol");
7166 return false;
7167 }
7168 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7169
Daniel Sandersf173dda2015-09-22 10:50:09 +00007170 CpSaveLocation = Save;
7171 CpSaveLocationIsRegister = SaveIsReg;
7172
Toma Tabacu8874eac2015-02-18 13:46:53 +00007173 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7174 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007175 return false;
7176}
7177
Daniel Sandersf173dda2015-09-22 10:50:09 +00007178bool MipsAsmParser::parseDirectiveCPReturn() {
7179 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7180 CpSaveLocationIsRegister);
7181 return false;
7182}
7183
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007184bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007185 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007186 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7187 const AsmToken &Tok = Parser.getTok();
7188
7189 if (Tok.getString() == "2008") {
7190 Parser.Lex();
7191 getTargetStreamer().emitDirectiveNaN2008();
7192 return false;
7193 } else if (Tok.getString() == "legacy") {
7194 Parser.Lex();
7195 getTargetStreamer().emitDirectiveNaNLegacy();
7196 return false;
7197 }
7198 }
7199 // If we don't recognize the option passed to the .nan
7200 // directive (e.g. no option or unknown option), emit an error.
7201 reportParseError("invalid option in .nan directive");
7202 return false;
7203}
7204
Jack Carter0b744b32012-10-04 02:29:46 +00007205bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007206 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00007207 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00007208 const AsmToken &Tok = Parser.getTok();
7209
7210 if (Tok.getString() == "noat") {
7211 return parseSetNoAtDirective();
7212 } else if (Tok.getString() == "at") {
7213 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00007214 } else if (Tok.getString() == "arch") {
7215 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00007216 } else if (Tok.getString() == "bopt") {
7217 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
7218 getParser().Lex();
7219 return false;
7220 } else if (Tok.getString() == "nobopt") {
7221 // We're already running in nobopt mode, so nothing to do.
7222 getParser().Lex();
7223 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007224 } else if (Tok.getString() == "fp") {
7225 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007226 } else if (Tok.getString() == "oddspreg") {
7227 return parseSetOddSPRegDirective();
7228 } else if (Tok.getString() == "nooddspreg") {
7229 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00007230 } else if (Tok.getString() == "pop") {
7231 return parseSetPopDirective();
7232 } else if (Tok.getString() == "push") {
7233 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00007234 } else if (Tok.getString() == "reorder") {
7235 return parseSetReorderDirective();
7236 } else if (Tok.getString() == "noreorder") {
7237 return parseSetNoReorderDirective();
7238 } else if (Tok.getString() == "macro") {
7239 return parseSetMacroDirective();
7240 } else if (Tok.getString() == "nomacro") {
7241 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00007242 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00007243 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007244 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00007245 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007246 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007247 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007248 getTargetStreamer().emitDirectiveSetNoMicroMips();
7249 Parser.eatToEndOfStatement();
7250 return false;
7251 } else if (Tok.getString() == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007252 if (hasMips64r6()) {
Simon Atanasyan478220f2018-05-24 07:36:00 +00007253 Error(Tok.getLoc(),
7254 ".set micromips directive is not supported with MIPS64R6");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007255 return false;
7256 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007257 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00007258 } else if (Tok.getString() == "mips0") {
7259 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00007260 } else if (Tok.getString() == "mips1") {
7261 return parseSetFeature(Mips::FeatureMips1);
7262 } else if (Tok.getString() == "mips2") {
7263 return parseSetFeature(Mips::FeatureMips2);
7264 } else if (Tok.getString() == "mips3") {
7265 return parseSetFeature(Mips::FeatureMips3);
7266 } else if (Tok.getString() == "mips4") {
7267 return parseSetFeature(Mips::FeatureMips4);
7268 } else if (Tok.getString() == "mips5") {
7269 return parseSetFeature(Mips::FeatureMips5);
7270 } else if (Tok.getString() == "mips32") {
7271 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00007272 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007273 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007274 } else if (Tok.getString() == "mips32r3") {
7275 return parseSetFeature(Mips::FeatureMips32r3);
7276 } else if (Tok.getString() == "mips32r5") {
7277 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007278 } else if (Tok.getString() == "mips32r6") {
7279 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007280 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007281 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007282 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007283 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007284 } else if (Tok.getString() == "mips64r3") {
7285 return parseSetFeature(Mips::FeatureMips64r3);
7286 } else if (Tok.getString() == "mips64r5") {
7287 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007288 } else if (Tok.getString() == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007289 if (inMicroMipsMode()) {
7290 Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS");
7291 return false;
7292 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007293 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00007294 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007295 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00007296 } else if (Tok.getString() == "dspr2") {
7297 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00007298 } else if (Tok.getString() == "nodsp") {
7299 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00007300 } else if (Tok.getString() == "msa") {
7301 return parseSetMsaDirective();
7302 } else if (Tok.getString() == "nomsa") {
7303 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00007304 } else if (Tok.getString() == "mt") {
7305 return parseSetMtDirective();
7306 } else if (Tok.getString() == "nomt") {
7307 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00007308 } else if (Tok.getString() == "softfloat") {
7309 return parseSetSoftFloatDirective();
7310 } else if (Tok.getString() == "hardfloat") {
7311 return parseSetHardFloatDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007312 } else if (Tok.getString() == "crc") {
7313 return parseSetFeature(Mips::FeatureCRC);
7314 } else if (Tok.getString() == "nocrc") {
7315 return parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007316 } else if (Tok.getString() == "virt") {
7317 return parseSetFeature(Mips::FeatureVirt);
7318 } else if (Tok.getString() == "novirt") {
7319 return parseSetNoVirtDirective();
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007320 } else if (Tok.getString() == "ginv") {
7321 return parseSetFeature(Mips::FeatureGINV);
7322 } else if (Tok.getString() == "noginv") {
7323 return parseSetNoGINVDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00007324 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00007325 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00007326 parseSetAssignment();
7327 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00007328 }
Jack Carter07c818d2013-01-25 01:31:34 +00007329
Jack Carter0b744b32012-10-04 02:29:46 +00007330 return true;
7331}
7332
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007333/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007334/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007335bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007336 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007337 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007338 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007339 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007340 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007341 return true;
7342
7343 getParser().getStreamer().EmitValue(Value, Size);
7344
7345 if (getLexer().is(AsmToken::EndOfStatement))
7346 break;
7347
Jack Carter07c818d2013-01-25 01:31:34 +00007348 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007349 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007350 Parser.Lex();
7351 }
7352 }
7353
7354 Parser.Lex();
7355 return false;
7356}
7357
Vladimir Medic4c299852013-11-06 11:27:05 +00007358/// parseDirectiveGpWord
7359/// ::= .gpword local_sym
7360bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007361 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007362 const MCExpr *Value;
7363 // EmitGPRel32Value requires an expression, so we are using base class
7364 // method to evaluate the expression.
7365 if (getParser().parseExpression(Value))
7366 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007367 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007368
Vladimir Medice10c1122013-11-13 13:18:04 +00007369 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007370 return Error(getLexer().getLoc(),
7371 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007372 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007373 return false;
7374}
7375
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007376/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007377/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007378bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007379 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007380 const MCExpr *Value;
7381 // EmitGPRel64Value requires an expression, so we are using base class
7382 // method to evaluate the expression.
7383 if (getParser().parseExpression(Value))
7384 return true;
7385 getParser().getStreamer().EmitGPRel64Value(Value);
7386
7387 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007388 return Error(getLexer().getLoc(),
7389 "unexpected token, expected end of statement");
7390 Parser.Lex(); // Eat EndOfStatement token.
7391 return false;
7392}
7393
7394/// parseDirectiveDtpRelWord
7395/// ::= .dtprelword tls_sym
7396bool MipsAsmParser::parseDirectiveDtpRelWord() {
7397 MCAsmParser &Parser = getParser();
7398 const MCExpr *Value;
7399 // EmitDTPRel32Value requires an expression, so we are using base class
7400 // method to evaluate the expression.
7401 if (getParser().parseExpression(Value))
7402 return true;
7403 getParser().getStreamer().EmitDTPRel32Value(Value);
7404
7405 if (getLexer().isNot(AsmToken::EndOfStatement))
7406 return Error(getLexer().getLoc(),
7407 "unexpected token, expected end of statement");
7408 Parser.Lex(); // Eat EndOfStatement token.
7409 return false;
7410}
7411
7412/// parseDirectiveDtpRelDWord
7413/// ::= .dtpreldword tls_sym
7414bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7415 MCAsmParser &Parser = getParser();
7416 const MCExpr *Value;
7417 // EmitDTPRel64Value requires an expression, so we are using base class
7418 // method to evaluate the expression.
7419 if (getParser().parseExpression(Value))
7420 return true;
7421 getParser().getStreamer().EmitDTPRel64Value(Value);
7422
7423 if (getLexer().isNot(AsmToken::EndOfStatement))
7424 return Error(getLexer().getLoc(),
7425 "unexpected token, expected end of statement");
7426 Parser.Lex(); // Eat EndOfStatement token.
7427 return false;
7428}
7429
7430/// parseDirectiveTpRelWord
7431/// ::= .tprelword tls_sym
7432bool MipsAsmParser::parseDirectiveTpRelWord() {
7433 MCAsmParser &Parser = getParser();
7434 const MCExpr *Value;
7435 // EmitTPRel32Value requires an expression, so we are using base class
7436 // method to evaluate the expression.
7437 if (getParser().parseExpression(Value))
7438 return true;
7439 getParser().getStreamer().EmitTPRel32Value(Value);
7440
7441 if (getLexer().isNot(AsmToken::EndOfStatement))
7442 return Error(getLexer().getLoc(),
7443 "unexpected token, expected end of statement");
7444 Parser.Lex(); // Eat EndOfStatement token.
7445 return false;
7446}
7447
7448/// parseDirectiveTpRelDWord
7449/// ::= .tpreldword tls_sym
7450bool MipsAsmParser::parseDirectiveTpRelDWord() {
7451 MCAsmParser &Parser = getParser();
7452 const MCExpr *Value;
7453 // EmitTPRel64Value requires an expression, so we are using base class
7454 // method to evaluate the expression.
7455 if (getParser().parseExpression(Value))
7456 return true;
7457 getParser().getStreamer().EmitTPRel64Value(Value);
7458
7459 if (getLexer().isNot(AsmToken::EndOfStatement))
7460 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007461 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007462 Parser.Lex(); // Eat EndOfStatement token.
7463 return false;
7464}
7465
Jack Carter0cd3c192014-01-06 23:27:31 +00007466bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007467 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007468 // Get the option token.
7469 AsmToken Tok = Parser.getTok();
7470 // At the moment only identifiers are supported.
7471 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007472 return Error(Parser.getTok().getLoc(),
7473 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007474 }
7475
7476 StringRef Option = Tok.getIdentifier();
7477
7478 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007479 // MipsAsmParser needs to know if the current PIC mode changes.
7480 IsPicEnabled = false;
7481
Jack Carter0cd3c192014-01-06 23:27:31 +00007482 getTargetStreamer().emitDirectiveOptionPic0();
7483 Parser.Lex();
7484 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007485 return Error(Parser.getTok().getLoc(),
7486 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007487 }
7488 return false;
7489 }
7490
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007491 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007492 // MipsAsmParser needs to know if the current PIC mode changes.
7493 IsPicEnabled = true;
7494
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007495 getTargetStreamer().emitDirectiveOptionPic2();
7496 Parser.Lex();
7497 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007498 return Error(Parser.getTok().getLoc(),
7499 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007500 }
7501 return false;
7502 }
7503
Jack Carter0cd3c192014-01-06 23:27:31 +00007504 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007505 Warning(Parser.getTok().getLoc(),
7506 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007507 Parser.eatToEndOfStatement();
7508 return false;
7509}
7510
Toma Tabacu9ca50962015-04-16 09:53:47 +00007511/// parseInsnDirective
7512/// ::= .insn
7513bool MipsAsmParser::parseInsnDirective() {
7514 // If this is not the end of the statement, report an error.
7515 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7516 reportParseError("unexpected token, expected end of statement");
7517 return false;
7518 }
7519
7520 // The actual label marking happens in
7521 // MipsELFStreamer::createPendingLabelRelocs().
7522 getTargetStreamer().emitDirectiveInsn();
7523
7524 getParser().Lex(); // Eat EndOfStatement token.
7525 return false;
7526}
7527
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007528/// parseRSectionDirective
7529/// ::= .rdata
7530bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7531 // If this is not the end of the statement, report an error.
7532 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7533 reportParseError("unexpected token, expected end of statement");
7534 return false;
7535 }
7536
7537 MCSection *ELFSection = getContext().getELFSection(
7538 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7539 getParser().getStreamer().SwitchSection(ELFSection);
7540
7541 getParser().Lex(); // Eat EndOfStatement token.
7542 return false;
7543}
7544
Simon Atanasyanbe186202016-02-11 06:45:54 +00007545/// parseSSectionDirective
7546/// ::= .sbss
7547/// ::= .sdata
7548bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7549 // If this is not the end of the statement, report an error.
7550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7551 reportParseError("unexpected token, expected end of statement");
7552 return false;
7553 }
7554
7555 MCSection *ELFSection = getContext().getELFSection(
7556 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7557 getParser().getStreamer().SwitchSection(ELFSection);
7558
7559 getParser().Lex(); // Eat EndOfStatement token.
7560 return false;
7561}
7562
Daniel Sanders7e527422014-07-10 13:38:23 +00007563/// parseDirectiveModule
7564/// ::= .module oddspreg
7565/// ::= .module nooddspreg
7566/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007567/// ::= .module softfloat
7568/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007569/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007570/// ::= .module crc
7571/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007572/// ::= .module virt
7573/// ::= .module novirt
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007574/// ::= .module ginv
7575/// ::= .module noginv
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007576bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007577 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007578 MCAsmLexer &Lexer = getLexer();
7579 SMLoc L = Lexer.getLoc();
7580
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007581 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007582 // TODO : get a better message.
7583 reportParseError(".module directive must appear before any code");
7584 return false;
7585 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007586
Toma Tabacuc405c822015-01-23 10:40:19 +00007587 StringRef Option;
7588 if (Parser.parseIdentifier(Option)) {
7589 reportParseError("expected .module option identifier");
7590 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007591 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007592
Toma Tabacuc405c822015-01-23 10:40:19 +00007593 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007594 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007595
Toma Tabacu3c499582015-06-25 10:56:57 +00007596 // Synchronize the abiflags information with the FeatureBits information we
7597 // changed above.
7598 getTargetStreamer().updateABIInfo(*this);
7599
7600 // If printing assembly, use the recently updated abiflags information.
7601 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7602 // emitted at the end).
7603 getTargetStreamer().emitDirectiveModuleOddSPReg();
7604
Toma Tabacuc405c822015-01-23 10:40:19 +00007605 // If this is not the end of the statement, report an error.
7606 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7607 reportParseError("unexpected token, expected end of statement");
7608 return false;
7609 }
7610
7611 return false; // parseDirectiveModule has finished successfully.
7612 } else if (Option == "nooddspreg") {
7613 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007614 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007615 }
7616
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007617 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007618
Toma Tabacu3c499582015-06-25 10:56:57 +00007619 // Synchronize the abiflags information with the FeatureBits information we
7620 // changed above.
7621 getTargetStreamer().updateABIInfo(*this);
7622
7623 // If printing assembly, use the recently updated abiflags information.
7624 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7625 // emitted at the end).
7626 getTargetStreamer().emitDirectiveModuleOddSPReg();
7627
Toma Tabacuc405c822015-01-23 10:40:19 +00007628 // If this is not the end of the statement, report an error.
7629 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7630 reportParseError("unexpected token, expected end of statement");
7631 return false;
7632 }
7633
7634 return false; // parseDirectiveModule has finished successfully.
7635 } else if (Option == "fp") {
7636 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007637 } else if (Option == "softfloat") {
7638 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7639
7640 // Synchronize the ABI Flags information with the FeatureBits information we
7641 // updated above.
7642 getTargetStreamer().updateABIInfo(*this);
7643
7644 // If printing assembly, use the recently updated ABI Flags information.
7645 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7646 // emitted later).
7647 getTargetStreamer().emitDirectiveModuleSoftFloat();
7648
7649 // If this is not the end of the statement, report an error.
7650 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7651 reportParseError("unexpected token, expected end of statement");
7652 return false;
7653 }
7654
7655 return false; // parseDirectiveModule has finished successfully.
7656 } else if (Option == "hardfloat") {
7657 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7658
7659 // Synchronize the ABI Flags information with the FeatureBits information we
7660 // updated above.
7661 getTargetStreamer().updateABIInfo(*this);
7662
7663 // If printing assembly, use the recently updated ABI Flags information.
7664 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7665 // emitted later).
7666 getTargetStreamer().emitDirectiveModuleHardFloat();
7667
7668 // If this is not the end of the statement, report an error.
7669 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7670 reportParseError("unexpected token, expected end of statement");
7671 return false;
7672 }
7673
7674 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007675 } else if (Option == "mt") {
7676 setModuleFeatureBits(Mips::FeatureMT, "mt");
7677
7678 // Synchronize the ABI Flags information with the FeatureBits information we
7679 // updated above.
7680 getTargetStreamer().updateABIInfo(*this);
7681
Simon Dardisd9611922017-07-11 21:36:58 +00007682 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007683 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7684 // emitted later).
7685 getTargetStreamer().emitDirectiveModuleMT();
7686
7687 // If this is not the end of the statement, report an error.
7688 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7689 reportParseError("unexpected token, expected end of statement");
7690 return false;
7691 }
7692
7693 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007694 } else if (Option == "crc") {
7695 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7696
7697 // Synchronize the ABI Flags information with the FeatureBits information we
7698 // updated above.
7699 getTargetStreamer().updateABIInfo(*this);
7700
7701 // If printing assembly, use the recently updated ABI Flags information.
7702 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7703 // emitted later).
7704 getTargetStreamer().emitDirectiveModuleCRC();
7705
7706 // If this is not the end of the statement, report an error.
7707 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7708 reportParseError("unexpected token, expected end of statement");
7709 return false;
7710 }
7711
7712 return false; // parseDirectiveModule has finished successfully.
7713 } else if (Option == "nocrc") {
7714 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7715
7716 // Synchronize the ABI Flags information with the FeatureBits information we
7717 // updated above.
7718 getTargetStreamer().updateABIInfo(*this);
7719
7720 // If printing assembly, use the recently updated ABI Flags information.
7721 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7722 // emitted later).
7723 getTargetStreamer().emitDirectiveModuleNoCRC();
7724
7725 // If this is not the end of the statement, report an error.
7726 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7727 reportParseError("unexpected token, expected end of statement");
7728 return false;
7729 }
7730
7731 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007732 } else if (Option == "virt") {
7733 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7734
7735 // Synchronize the ABI Flags information with the FeatureBits information we
7736 // updated above.
7737 getTargetStreamer().updateABIInfo(*this);
7738
7739 // If printing assembly, use the recently updated ABI Flags information.
7740 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7741 // emitted later).
7742 getTargetStreamer().emitDirectiveModuleVirt();
7743
7744 // If this is not the end of the statement, report an error.
7745 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7746 reportParseError("unexpected token, expected end of statement");
7747 return false;
7748 }
7749
7750 return false; // parseDirectiveModule has finished successfully.
7751 } else if (Option == "novirt") {
7752 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7753
7754 // Synchronize the ABI Flags information with the FeatureBits information we
7755 // updated above.
7756 getTargetStreamer().updateABIInfo(*this);
7757
7758 // If printing assembly, use the recently updated ABI Flags information.
7759 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7760 // emitted later).
7761 getTargetStreamer().emitDirectiveModuleNoVirt();
7762
7763 // If this is not the end of the statement, report an error.
7764 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7765 reportParseError("unexpected token, expected end of statement");
7766 return false;
7767 }
7768
7769 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007770 } else if (Option == "ginv") {
7771 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
7772
7773 // Synchronize the ABI Flags information with the FeatureBits information we
7774 // updated above.
7775 getTargetStreamer().updateABIInfo(*this);
7776
7777 // If printing assembly, use the recently updated ABI Flags information.
7778 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7779 // emitted later).
7780 getTargetStreamer().emitDirectiveModuleGINV();
7781
7782 // If this is not the end of the statement, report an error.
7783 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7784 reportParseError("unexpected token, expected end of statement");
7785 return false;
7786 }
7787
7788 return false; // parseDirectiveModule has finished successfully.
7789 } else if (Option == "noginv") {
7790 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
7791
7792 // Synchronize the ABI Flags information with the FeatureBits information we
7793 // updated above.
7794 getTargetStreamer().updateABIInfo(*this);
7795
7796 // If printing assembly, use the recently updated ABI Flags information.
7797 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7798 // emitted later).
7799 getTargetStreamer().emitDirectiveModuleNoGINV();
7800
7801 // If this is not the end of the statement, report an error.
7802 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7803 reportParseError("unexpected token, expected end of statement");
7804 return false;
7805 }
7806
7807 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007808 } else {
7809 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7810 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007811}
7812
7813/// parseDirectiveModuleFP
7814/// ::= =32
7815/// ::= =xx
7816/// ::= =64
7817bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007818 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007819 MCAsmLexer &Lexer = getLexer();
7820
7821 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007822 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007823 return false;
7824 }
7825 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007826
Daniel Sanders7e527422014-07-10 13:38:23 +00007827 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007828 if (!parseFpABIValue(FpABI, ".module"))
7829 return false;
7830
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007832 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007833 return false;
7834 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007835
Toma Tabacua64e5402015-06-25 12:44:38 +00007836 // Synchronize the abiflags information with the FeatureBits information we
7837 // changed above.
7838 getTargetStreamer().updateABIInfo(*this);
7839
7840 // If printing assembly, use the recently updated abiflags information.
7841 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7842 // emitted at the end).
7843 getTargetStreamer().emitDirectiveModuleFP();
7844
Daniel Sanders7e527422014-07-10 13:38:23 +00007845 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007846 return false;
7847}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007848
Daniel Sanders7e527422014-07-10 13:38:23 +00007849bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007850 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007851 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007852 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007853 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007854
7855 if (Lexer.is(AsmToken::Identifier)) {
7856 StringRef Value = Parser.getTok().getString();
7857 Parser.Lex();
7858
7859 if (Value != "xx") {
7860 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7861 return false;
7862 }
7863
7864 if (!isABI_O32()) {
7865 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7866 return false;
7867 }
7868
Daniel Sanders7e527422014-07-10 13:38:23 +00007869 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007870 if (ModuleLevelOptions) {
7871 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7872 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7873 } else {
7874 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7875 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7876 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007877 return true;
7878 }
7879
7880 if (Lexer.is(AsmToken::Integer)) {
7881 unsigned Value = Parser.getTok().getIntVal();
7882 Parser.Lex();
7883
7884 if (Value != 32 && Value != 64) {
7885 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7886 return false;
7887 }
7888
7889 if (Value == 32) {
7890 if (!isABI_O32()) {
7891 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7892 return false;
7893 }
7894
Daniel Sanders7e527422014-07-10 13:38:23 +00007895 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007896 if (ModuleLevelOptions) {
7897 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7898 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7899 } else {
7900 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7901 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7902 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007903 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007904 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007905 if (ModuleLevelOptions) {
7906 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7907 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7908 } else {
7909 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7910 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7911 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007912 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007913
Daniel Sanders7e527422014-07-10 13:38:23 +00007914 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007915 }
7916
7917 return false;
7918}
7919
Jack Carter0b744b32012-10-04 02:29:46 +00007920bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007921 // This returns false if this function recognizes the directive
7922 // regardless of whether it is successfully handles or reports an
7923 // error. Otherwise it returns true to give the generic parser a
7924 // chance at recognizing it.
7925
Rafael Espindola961d4692014-11-11 05:18:41 +00007926 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007927 StringRef IDVal = DirectiveID.getString();
7928
Nirav Dave996fc132016-05-05 14:15:46 +00007929 if (IDVal == ".cpload") {
7930 parseDirectiveCpLoad(DirectiveID.getLoc());
7931 return false;
7932 }
7933 if (IDVal == ".cprestore") {
7934 parseDirectiveCpRestore(DirectiveID.getLoc());
7935 return false;
7936 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007937 if (IDVal == ".dword") {
7938 parseDataDirective(8, DirectiveID.getLoc());
7939 return false;
7940 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007941 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007942 StringRef SymbolName;
7943
7944 if (Parser.parseIdentifier(SymbolName)) {
7945 reportParseError("expected identifier after .ent");
7946 return false;
7947 }
7948
7949 // There's an undocumented extension that allows an integer to
7950 // follow the name of the procedure which AFAICS is ignored by GAS.
7951 // Example: .ent foo,2
7952 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7953 if (getLexer().isNot(AsmToken::Comma)) {
7954 // Even though we accept this undocumented extension for compatibility
7955 // reasons, the additional integer argument does not actually change
7956 // the behaviour of the '.ent' directive, so we would like to discourage
7957 // its use. We do this by not referring to the extended version in
7958 // error messages which are not directly related to its use.
7959 reportParseError("unexpected token, expected end of statement");
7960 return false;
7961 }
7962 Parser.Lex(); // Eat the comma.
7963 const MCExpr *DummyNumber;
7964 int64_t DummyNumberVal;
7965 // If the user was explicitly trying to use the extended version,
7966 // we still give helpful extension-related error messages.
7967 if (Parser.parseExpression(DummyNumber)) {
7968 reportParseError("expected number after comma");
7969 return false;
7970 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007971 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007972 reportParseError("expected an absolute expression after comma");
7973 return false;
7974 }
7975 }
7976
7977 // If this is not the end of the statement, report an error.
7978 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7979 reportParseError("unexpected token, expected end of statement");
7980 return false;
7981 }
7982
Jim Grosbach6f482002015-05-18 18:43:14 +00007983 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007984
7985 getTargetStreamer().emitDirectiveEnt(*Sym);
7986 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007987 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007988 return false;
7989 }
7990
Jack Carter07c818d2013-01-25 01:31:34 +00007991 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007992 StringRef SymbolName;
7993
7994 if (Parser.parseIdentifier(SymbolName)) {
7995 reportParseError("expected identifier after .end");
7996 return false;
7997 }
7998
7999 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8000 reportParseError("unexpected token, expected end of statement");
8001 return false;
8002 }
8003
8004 if (CurrentFn == nullptr) {
8005 reportParseError(".end used without .ent");
8006 return false;
8007 }
8008
8009 if ((SymbolName != CurrentFn->getName())) {
8010 reportParseError(".end symbol does not match .ent symbol");
8011 return false;
8012 }
8013
8014 getTargetStreamer().emitDirectiveEnd(SymbolName);
8015 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008016 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008017 return false;
8018 }
8019
Jack Carter07c818d2013-01-25 01:31:34 +00008020 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008021 // .frame $stack_reg, frame_size_in_bytes, $return_reg
8022 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00008023 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008024 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8025 reportParseError("expected stack register");
8026 return false;
8027 }
8028
8029 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8030 if (!StackRegOpnd.isGPRAsmReg()) {
8031 reportParseError(StackRegOpnd.getStartLoc(),
8032 "expected general purpose register");
8033 return false;
8034 }
8035 unsigned StackReg = StackRegOpnd.getGPR32Reg();
8036
8037 if (Parser.getTok().is(AsmToken::Comma))
8038 Parser.Lex();
8039 else {
8040 reportParseError("unexpected token, expected comma");
8041 return false;
8042 }
8043
8044 // Parse the frame size.
8045 const MCExpr *FrameSize;
8046 int64_t FrameSizeVal;
8047
8048 if (Parser.parseExpression(FrameSize)) {
8049 reportParseError("expected frame size value");
8050 return false;
8051 }
8052
Jim Grosbach13760bd2015-05-30 01:25:56 +00008053 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008054 reportParseError("frame size not an absolute expression");
8055 return false;
8056 }
8057
8058 if (Parser.getTok().is(AsmToken::Comma))
8059 Parser.Lex();
8060 else {
8061 reportParseError("unexpected token, expected comma");
8062 return false;
8063 }
8064
8065 // Parse the return register.
8066 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00008067 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008068 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8069 reportParseError("expected return register");
8070 return false;
8071 }
8072
8073 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8074 if (!ReturnRegOpnd.isGPRAsmReg()) {
8075 reportParseError(ReturnRegOpnd.getStartLoc(),
8076 "expected general purpose register");
8077 return false;
8078 }
8079
8080 // If this is not the end of the statement, report an error.
8081 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8082 reportParseError("unexpected token, expected end of statement");
8083 return false;
8084 }
8085
8086 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8087 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008088 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008089 return false;
8090 }
8091
Jack Carter07c818d2013-01-25 01:31:34 +00008092 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008093 parseDirectiveSet();
8094 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008095 }
8096
Daniel Sandersd97a6342014-08-13 10:07:34 +00008097 if (IDVal == ".mask" || IDVal == ".fmask") {
8098 // .mask bitmask, frame_offset
8099 // bitmask: One bit for each register used.
8100 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8101 // first register is expected to be saved.
8102 // Examples:
8103 // .mask 0x80000000, -4
8104 // .fmask 0x80000000, -4
8105 //
Jack Carterbe332172012-09-07 00:48:02 +00008106
Daniel Sandersd97a6342014-08-13 10:07:34 +00008107 // Parse the bitmask
8108 const MCExpr *BitMask;
8109 int64_t BitMaskVal;
8110
8111 if (Parser.parseExpression(BitMask)) {
8112 reportParseError("expected bitmask value");
8113 return false;
8114 }
8115
Jim Grosbach13760bd2015-05-30 01:25:56 +00008116 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008117 reportParseError("bitmask not an absolute expression");
8118 return false;
8119 }
8120
8121 if (Parser.getTok().is(AsmToken::Comma))
8122 Parser.Lex();
8123 else {
8124 reportParseError("unexpected token, expected comma");
8125 return false;
8126 }
8127
8128 // Parse the frame_offset
8129 const MCExpr *FrameOffset;
8130 int64_t FrameOffsetVal;
8131
8132 if (Parser.parseExpression(FrameOffset)) {
8133 reportParseError("expected frame offset value");
8134 return false;
8135 }
8136
Jim Grosbach13760bd2015-05-30 01:25:56 +00008137 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008138 reportParseError("frame offset not an absolute expression");
8139 return false;
8140 }
8141
8142 // If this is not the end of the statement, report an error.
8143 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8144 reportParseError("unexpected token, expected end of statement");
8145 return false;
8146 }
8147
8148 if (IDVal == ".mask")
8149 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8150 else
8151 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008152 return false;
8153 }
8154
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008155 if (IDVal == ".nan")
8156 return parseDirectiveNaN();
8157
Jack Carter07c818d2013-01-25 01:31:34 +00008158 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008159 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008160 return false;
8161 }
8162
Rafael Espindolab59fb732014-03-28 18:50:26 +00008163 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008164 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008165 return false;
8166 }
8167
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008168 if (IDVal == ".dtprelword") {
8169 parseDirectiveDtpRelWord();
8170 return false;
8171 }
8172
8173 if (IDVal == ".dtpreldword") {
8174 parseDirectiveDtpRelDWord();
8175 return false;
8176 }
8177
8178 if (IDVal == ".tprelword") {
8179 parseDirectiveTpRelWord();
8180 return false;
8181 }
8182
8183 if (IDVal == ".tpreldword") {
8184 parseDirectiveTpRelDWord();
8185 return false;
8186 }
8187
Jack Carter07c818d2013-01-25 01:31:34 +00008188 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00008189 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00008190 return false;
8191 }
8192
Scott Egertond1aeb052016-02-15 16:11:51 +00008193 if (IDVal == ".hword") {
8194 parseDataDirective(2, DirectiveID.getLoc());
8195 return false;
8196 }
8197
Nirav Dave996fc132016-05-05 14:15:46 +00008198 if (IDVal == ".option") {
8199 parseDirectiveOption();
8200 return false;
8201 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008202
8203 if (IDVal == ".abicalls") {
8204 getTargetStreamer().emitDirectiveAbiCalls();
8205 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00008206 Error(Parser.getTok().getLoc(),
8207 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008208 }
8209 return false;
8210 }
8211
Nirav Dave996fc132016-05-05 14:15:46 +00008212 if (IDVal == ".cpsetup") {
8213 parseDirectiveCPSetup();
8214 return false;
8215 }
8216 if (IDVal == ".cpreturn") {
8217 parseDirectiveCPReturn();
8218 return false;
8219 }
8220 if (IDVal == ".module") {
8221 parseDirectiveModule();
8222 return false;
8223 }
8224 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8225 parseInternalDirectiveReallowModule();
8226 return false;
8227 }
8228 if (IDVal == ".insn") {
8229 parseInsnDirective();
8230 return false;
8231 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008232 if (IDVal == ".rdata") {
8233 parseRSectionDirective(".rodata");
8234 return false;
8235 }
Nirav Dave996fc132016-05-05 14:15:46 +00008236 if (IDVal == ".sbss") {
8237 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8238 return false;
8239 }
8240 if (IDVal == ".sdata") {
8241 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8242 return false;
8243 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008244
Rafael Espindola870c4e92012-01-11 03:56:41 +00008245 return true;
8246}
8247
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008248bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8249 // If this is not the end of the statement, report an error.
8250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8251 reportParseError("unexpected token, expected end of statement");
8252 return false;
8253 }
8254
8255 getTargetStreamer().reallowModuleDirective();
8256
8257 getParser().Lex(); // Eat EndOfStatement token.
8258 return false;
8259}
8260
Rafael Espindola870c4e92012-01-11 03:56:41 +00008261extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008262 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8263 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8264 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8265 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008266}
Jack Carterb4dbc172012-09-05 23:34:03 +00008267
8268#define GET_REGISTER_MATCHER
8269#define GET_MATCHER_IMPLEMENTATION
8270#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008271
8272bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8273 // Find the appropriate table for this asm variant.
8274 const MatchEntry *Start, *End;
8275 switch (VariantID) {
8276 default: llvm_unreachable("invalid variant!");
8277 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8278 }
8279 // Search the table.
8280 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8281 return MnemonicRange.first != MnemonicRange.second;
8282}