blob: 79e0c001a636cfdd6ca71cac52e015cbb1b58f87 [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
Simon Atanasyan69301c92018-05-29 15:58:06 +0000149 // Map of register aliases created via the .set directive.
150 StringMap<AsmToken> RegisterSets;
151
Daniel Sandersef638fe2014-10-03 15:37:37 +0000152 // Print a warning along with its fix-it message at the given range.
153 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
154 SMRange Range, bool ShowColors = true);
155
Simon Dardis6a319922018-05-25 16:15:48 +0000156 void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
157
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000158#define GET_ASSEMBLER_HEADER
159#include "MipsGenAsmMatcher.inc"
160
Daniel Sandersc5537422016-07-27 13:49:44 +0000161 unsigned
162 checkEarlyTargetMatchPredicate(MCInst &Inst,
163 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000164 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
165
Chad Rosier49963552012-10-13 00:26:04 +0000166 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000167 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000168 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000169 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000170
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000171 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000172 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000173
Toma Tabacu13964452014-09-04 13:23:44 +0000174 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000175
Toma Tabacu13964452014-09-04 13:23:44 +0000176 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000177
Craig Topper55bc6cb2017-02-08 02:54:12 +0000178 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
179
David Blaikie960ea3f2014-06-08 16:18:35 +0000180 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
181 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000182
Craig Topper56c590a2014-04-29 07:58:02 +0000183 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000184
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000185 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
186 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000187 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000188 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000189 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan69301c92018-05-29 15:58:06 +0000190 const AsmToken &Token,
191 SMLoc S);
192 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000193 SMLoc S);
194 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
195 OperandMatchResultTy parseImm(OperandVector &Operands);
196 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
197 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000198 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000199
David Blaikie960ea3f2014-06-08 16:18:35 +0000200 bool searchSymbolAlias(OperandVector &Operands);
201
Toma Tabacu13964452014-09-04 13:23:44 +0000202 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000203
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000204 enum MacroExpanderResultTy {
205 MER_NotAMacro,
206 MER_Success,
207 MER_Fail,
208 };
Jack Carter30a59822012-10-04 04:03:53 +0000209
Matheus Almeida3813d572014-06-19 14:39:14 +0000210 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000211 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
212 MCStreamer &Out,
213 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000214
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
216 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000217
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000218 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000219 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000220 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000221
Toma Tabacuf712ede2015-06-17 14:31:51 +0000222 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
223 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000224 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000225
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000226 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
227
Toma Tabacu00e98672015-05-01 12:19:27 +0000228 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000229 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000230
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000231 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
232 SMLoc IDLoc, MCStreamer &Out,
233 const MCSubtargetInfo *STI);
234
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000235 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
236 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 SMLoc IDLoc, MCStreamer &Out,
238 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000239
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000240 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000242
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000243 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +0000244 const MCSubtargetInfo *STI, bool IsLoad);
Daniel Sandersfba875f2016-04-29 13:43:45 +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
Stefan Maksimovic0a239982018-07-09 13:06:44 +0000258 bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
260 const bool Signed);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000261
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
Vladimir Medic4c299852013-11-06 11:27:05 +0000357 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000358 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000359 bool parseDirectiveDtpRelWord();
360 bool parseDirectiveDtpRelDWord();
361 bool parseDirectiveTpRelWord();
362 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000363 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000364 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000365 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
366 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000367
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000368 bool parseInternalDirectiveReallowModule();
369
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000370 bool eatComma(StringRef ErrorStr);
371
Jack Carter1ac53222013-02-20 23:11:17 +0000372 int matchCPURegisterName(StringRef Symbol);
373
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000374 int matchHWRegsRegisterName(StringRef Symbol);
375
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000376 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000377
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000378 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000379
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000380 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000381
Jack Carter5dc8ac92013-09-25 23:50:44 +0000382 int matchMSA128RegisterName(StringRef Name);
383
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000384 int matchMSA128CtrlRegisterName(StringRef Name);
385
Jack Carterd0bd6422013-04-18 00:41:53 +0000386 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000387
Toma Tabacu89a712b2015-04-15 10:48:56 +0000388 /// Returns the internal register number for the current AT. Also checks if
389 /// the current AT is unavailable (set to $0) and gives an error if it is.
390 /// This should be used in pseudo-instruction expansions which need AT.
391 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000392
Simon Dardis3aa8a902017-02-06 12:43:46 +0000393 bool canUseATReg();
394
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000395 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
396 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000397
398 // Helper function that checks if the value of a vector index is within the
399 // boundaries of accepted values for each RegisterKind
400 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
401 bool validateMSAIndex(int Val, int RegKind);
402
Daniel Sandersf0df2212014-08-04 12:20:00 +0000403 // Selects a new architecture by updating the FeatureBits with the necessary
404 // info including implied dependencies.
405 // Internally, it clears all the feature bits related to *any* architecture
406 // and selects the new one using the ToggleFeature functionality of the
407 // MCSubtargetInfo object that handles implied dependencies. The reason we
408 // clear all the arch related bits manually is because ToggleFeature only
409 // clears the features that imply the feature being cleared and not the
410 // features implied by the feature being cleared. This is easier to see
411 // with an example:
412 // --------------------------------------------------
413 // | Feature | Implies |
414 // | -------------------------------------------------|
415 // | FeatureMips1 | None |
416 // | FeatureMips2 | FeatureMips1 |
417 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
418 // | FeatureMips4 | FeatureMips3 |
419 // | ... | |
420 // --------------------------------------------------
421 //
422 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
423 // FeatureMipsGP64 | FeatureMips1)
424 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
425 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000426 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000427 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000428 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
429 STI.setFeatureBits(FeatureBits);
430 setAvailableFeatures(
431 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000432 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000433 }
434
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000435 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000436 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000437 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000438 setAvailableFeatures(
439 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000440 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000441 }
442 }
443
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000444 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000445 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000446 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000447 setAvailableFeatures(
448 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000449 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000450 }
451 }
452
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000453 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
454 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000456 }
457
458 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
459 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000460 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000461 }
462
Rafael Espindola870c4e92012-01-11 03:56:41 +0000463public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000464 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000465 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000466 Match_RequiresDifferentOperands,
467 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000468 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000469 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000470 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000471 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000472 Match_RequiresPosSizeRange0_32,
473 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000474 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000475#define GET_OPERAND_DIAGNOSTIC_TYPES
476#include "MipsGenAsmMatcher.inc"
477#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000478 };
479
Akira Hatanakab11ef082015-11-14 06:35:56 +0000480 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000481 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000482 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000483 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
484 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000485 MCAsmParserExtension::Initialize(parser);
486
Toma Tabacu11e14a92015-04-21 11:50:52 +0000487 parser.addAliasForDirective(".asciiz", ".asciz");
Simon Atanasyanb5244592018-07-25 07:07:43 +0000488 parser.addAliasForDirective(".hword", ".2byte");
489 parser.addAliasForDirective(".word", ".4byte");
490 parser.addAliasForDirective(".dword", ".8byte");
Toma Tabacu11e14a92015-04-21 11:50:52 +0000491
Jack Carterb4dbc172012-09-05 23:34:03 +0000492 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000494
Toma Tabacu9db22db2014-09-09 10:15:38 +0000495 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000496 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000497 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000498
Toma Tabacu9db22db2014-09-09 10:15:38 +0000499 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000500 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000501 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000502
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 getTargetStreamer().updateABIInfo(*this);
504
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000505 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000506 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000507
508 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000509
Rafael Espindola699281c2016-05-18 11:58:50 +0000510 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000511
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000512 IsCpRestoreSet = false;
513 CpRestoreOffset = -1;
514
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000515 const Triple &TheTriple = sti.getTargetTriple();
Alexander Richardson85e200e2018-06-25 16:49:20 +0000516 IsLittleEndian = TheTriple.isLittleEndian();
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000517
518 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
519 report_fatal_error("microMIPS64R6 is not supported", false);
Simon Dardisaf38a8f2018-06-19 16:05:44 +0000520
521 if (!isABI_O32() && inMicroMipsMode())
522 report_fatal_error("microMIPS64 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000523 }
524
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000525 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
526 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
527
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000528 bool isGP64bit() const {
529 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
530 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000531
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 bool isFP64bit() const {
533 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Eric Christophera5762812015-01-26 17:33:46 +0000536 const MipsABIInfo &getABI() const { return ABI; }
537 bool isABI_N32() const { return ABI.IsN32(); }
538 bool isABI_N64() const { return ABI.IsN64(); }
539 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 bool isABI_FPXX() const {
541 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
542 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000544 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000545 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000546 }
547
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 bool hasMips1() const {
553 return getSTI().getFeatureBits()[Mips::FeatureMips1];
554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000556 bool hasMips2() const {
557 return getSTI().getFeatureBits()[Mips::FeatureMips2];
558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000560 bool hasMips3() const {
561 return getSTI().getFeatureBits()[Mips::FeatureMips3];
562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000564 bool hasMips4() const {
565 return getSTI().getFeatureBits()[Mips::FeatureMips4];
566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000568 bool hasMips5() const {
569 return getSTI().getFeatureBits()[Mips::FeatureMips5];
570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000571
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000572 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000573 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000576 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000577 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000580 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000581 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000584 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000585 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Daniel Sanders17793142015-02-18 16:24:50 +0000588 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000589 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000591
Daniel Sanders17793142015-02-18 16:24:50 +0000592 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000593 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000594 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000595
Daniel Sanders17793142015-02-18 16:24:50 +0000596 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000597 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000598 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000599
Daniel Sanders17793142015-02-18 16:24:50 +0000600 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000601 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000603
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000604 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000605 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000606 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000607
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000608 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000609 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000610 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000611
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000612 bool hasDSP() const {
613 return getSTI().getFeatureBits()[Mips::FeatureDSP];
614 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000615
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000616 bool hasDSPR2() const {
617 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
618 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000619
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000620 bool hasDSPR3() const {
621 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
622 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000623
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000624 bool hasMSA() const {
625 return getSTI().getFeatureBits()[Mips::FeatureMSA];
626 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000627
Kai Nackee0245392015-01-27 19:11:28 +0000628 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000629 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000630 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000631
Daniel Sandersa6994442015-08-18 12:33:54 +0000632 bool inPicMode() {
633 return IsPicEnabled;
634 }
635
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000636 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000637 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000638 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000639
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000640 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000641 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000642 }
643
Eric Christophere8ae3e32015-05-07 23:10:21 +0000644 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000645 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000646 }
Simon Dardisae719c52017-07-11 18:03:20 +0000647 bool hasMT() const {
648 return getSTI().getFeatureBits()[Mips::FeatureMT];
649 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000650
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000651 bool hasCRC() const {
652 return getSTI().getFeatureBits()[Mips::FeatureCRC];
653 }
654
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000655 bool hasVirt() const {
656 return getSTI().getFeatureBits()[Mips::FeatureVirt];
657 }
658
Petar Jovanovicdaf51692018-05-17 16:30:32 +0000659 bool hasGINV() const {
660 return getSTI().getFeatureBits()[Mips::FeatureGINV];
661 }
662
Toma Tabacud9d344b2015-04-27 14:05:04 +0000663 /// Warn if RegIndex is the same as the current AT.
664 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000665
666 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000667
668 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000669
670 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
671 AsmToken::TokenKind OperatorToken,
672 MCContext &Ctx) override {
673 switch(OperatorToken) {
674 default:
675 llvm_unreachable("Unknown token");
676 return nullptr;
677 case AsmToken::PercentCall16:
678 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
679 case AsmToken::PercentCall_Hi:
680 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
681 case AsmToken::PercentCall_Lo:
682 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
683 case AsmToken::PercentDtprel_Hi:
684 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
685 case AsmToken::PercentDtprel_Lo:
686 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
687 case AsmToken::PercentGot:
688 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
689 case AsmToken::PercentGot_Disp:
690 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
691 case AsmToken::PercentGot_Hi:
692 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
693 case AsmToken::PercentGot_Lo:
694 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
695 case AsmToken::PercentGot_Ofst:
696 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
697 case AsmToken::PercentGot_Page:
698 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
699 case AsmToken::PercentGottprel:
700 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
701 case AsmToken::PercentGp_Rel:
702 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
703 case AsmToken::PercentHi:
704 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
705 case AsmToken::PercentHigher:
706 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
707 case AsmToken::PercentHighest:
708 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
709 case AsmToken::PercentLo:
710 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
711 case AsmToken::PercentNeg:
712 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
713 case AsmToken::PercentPcrel_Hi:
714 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
715 case AsmToken::PercentPcrel_Lo:
716 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
717 case AsmToken::PercentTlsgd:
718 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
719 case AsmToken::PercentTlsldm:
720 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
721 case AsmToken::PercentTprel_Hi:
722 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
723 case AsmToken::PercentTprel_Lo:
724 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
725 }
726 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000727};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000728
729/// MipsOperand - Instances of this class represent a parsed Mips machine
730/// instruction.
731class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000732public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000733 /// Broad categories of register classes
734 /// The exact class is finalized by the render method.
735 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000736 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000737 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000738 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000739 RegKind_FCC = 4, /// FCC
740 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
741 RegKind_MSACtrl = 16, /// MSA control registers
742 RegKind_COP2 = 32, /// COP2
743 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
744 /// context).
745 RegKind_CCR = 128, /// CCR
746 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000747 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000748 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000749 /// Potentially any (e.g. $1)
750 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
751 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000752 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000753 };
754
755private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000756 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000757 k_Immediate, /// An immediate (possibly involving symbol references)
758 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000759 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000760 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000761 k_RegList, /// A physical register list
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) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000770 case k_Memory:
771 delete Mem.Base;
772 break;
773 case k_RegList:
774 delete RegList.List;
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000775 break;
776 case k_Immediate:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000777 case k_RegisterIndex:
778 case k_Token:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000779 break;
780 }
781 }
782
David Blaikie960ea3f2014-06-08 16:18:35 +0000783private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 /// For diagnostics, and checking the assembler temporary
785 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000786
Eric Christopher8996c5d2013-03-15 00:42:55 +0000787 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000788 const char *Data;
789 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000790 };
791
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 struct RegIdxOp {
793 unsigned Index; /// Index into the register class
794 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000795 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000797 };
798
799 struct ImmOp {
800 const MCExpr *Val;
801 };
802
803 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000805 const MCExpr *Off;
806 };
807
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000808 struct RegListOp {
809 SmallVector<unsigned, 10> *List;
810 };
811
Jack Carterb4dbc172012-09-05 23:34:03 +0000812 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000813 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000815 struct ImmOp Imm;
816 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000817 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000818 };
819
820 SMLoc StartLoc, EndLoc;
821
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000822 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000823 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
824 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000825 const MCRegisterInfo *RegInfo,
826 SMLoc S, SMLoc E,
827 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000828 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000829 Op->RegIdx.Index = Index;
830 Op->RegIdx.RegInfo = RegInfo;
831 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000832 Op->RegIdx.Tok.Data = Str.data();
833 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000834 Op->StartLoc = S;
835 Op->EndLoc = E;
836 return Op;
837 }
838
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000839public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 /// Coerce the register to GPR32 and return the real register for the current
841 /// target.
842 unsigned getGPR32Reg() const {
843 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000844 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 unsigned ClassID = Mips::GPR32RegClassID;
846 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000847 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000848
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000849 /// Coerce the register to GPR32 and return the real register for the current
850 /// target.
851 unsigned getGPRMM16Reg() const {
852 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
853 unsigned ClassID = Mips::GPR32RegClassID;
854 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
855 }
856
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000857 /// Coerce the register to GPR64 and return the real register for the current
858 /// target.
859 unsigned getGPR64Reg() const {
860 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
861 unsigned ClassID = Mips::GPR64RegClassID;
862 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000863 }
864
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865private:
866 /// Coerce the register to AFGR64 and return the real register for the current
867 /// target.
868 unsigned getAFGR64Reg() const {
869 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
870 if (RegIdx.Index % 2 != 0)
871 AsmParser.Warning(StartLoc, "Float register should be even.");
872 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
873 .getRegister(RegIdx.Index / 2);
874 }
875
876 /// Coerce the register to FGR64 and return the real register for the current
877 /// target.
878 unsigned getFGR64Reg() const {
879 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
880 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
881 .getRegister(RegIdx.Index);
882 }
883
884 /// Coerce the register to FGR32 and return the real register for the current
885 /// target.
886 unsigned getFGR32Reg() const {
887 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
888 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
889 .getRegister(RegIdx.Index);
890 }
891
892 /// Coerce the register to FGRH32 and return the real register for the current
893 /// target.
894 unsigned getFGRH32Reg() const {
895 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
896 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
897 .getRegister(RegIdx.Index);
898 }
899
900 /// Coerce the register to FCC and return the real register for the current
901 /// target.
902 unsigned getFCCReg() const {
903 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
904 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
905 .getRegister(RegIdx.Index);
906 }
907
908 /// Coerce the register to MSA128 and return the real register for the current
909 /// target.
910 unsigned getMSA128Reg() const {
911 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
912 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
913 // identical
914 unsigned ClassID = Mips::MSA128BRegClassID;
915 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
916 }
917
918 /// Coerce the register to MSACtrl and return the real register for the
919 /// current target.
920 unsigned getMSACtrlReg() const {
921 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
922 unsigned ClassID = Mips::MSACtrlRegClassID;
923 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
924 }
925
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000926 /// Coerce the register to COP0 and return the real register for the
927 /// current target.
928 unsigned getCOP0Reg() const {
929 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
930 unsigned ClassID = Mips::COP0RegClassID;
931 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
932 }
933
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000934 /// Coerce the register to COP2 and return the real register for the
935 /// current target.
936 unsigned getCOP2Reg() const {
937 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
938 unsigned ClassID = Mips::COP2RegClassID;
939 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
940 }
941
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000942 /// Coerce the register to COP3 and return the real register for the
943 /// current target.
944 unsigned getCOP3Reg() const {
945 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
946 unsigned ClassID = Mips::COP3RegClassID;
947 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
948 }
949
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000950 /// Coerce the register to ACC64DSP and return the real register for the
951 /// current target.
952 unsigned getACC64DSPReg() const {
953 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
954 unsigned ClassID = Mips::ACC64DSPRegClassID;
955 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
956 }
957
958 /// Coerce the register to HI32DSP and return the real register for the
959 /// current target.
960 unsigned getHI32DSPReg() const {
961 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
962 unsigned ClassID = Mips::HI32DSPRegClassID;
963 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
964 }
965
966 /// Coerce the register to LO32DSP and return the real register for the
967 /// current target.
968 unsigned getLO32DSPReg() const {
969 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
970 unsigned ClassID = Mips::LO32DSPRegClassID;
971 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
972 }
973
974 /// Coerce the register to CCR and return the real register for the
975 /// current target.
976 unsigned getCCRReg() const {
977 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
978 unsigned ClassID = Mips::CCRRegClassID;
979 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
980 }
981
982 /// Coerce the register to HWRegs and return the real register for the
983 /// current target.
984 unsigned getHWRegsReg() const {
985 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
986 unsigned ClassID = Mips::HWRegsRegClassID;
987 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
988 }
989
990public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000991 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000992 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000993 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000994 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000995 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000996 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000997 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000998 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000999 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001000
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001001 void addRegOperands(MCInst &Inst, unsigned N) const {
1002 llvm_unreachable("Use a custom parser instead");
1003 }
1004
Daniel Sanders21bce302014-04-01 12:35:23 +00001005 /// Render the operand to an MCInst as a GPR32
1006 /// Asserts if the wrong number of operands are requested, or the operand
1007 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +00001008 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1009 assert(N == 1 && "Invalid number of operands!");
1010 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1011 }
1012
1013 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1014 assert(N == 1 && "Invalid number of operands!");
1015 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1016 }
1017
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001018 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1019 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001020 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 }
1022
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001023 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1024 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001025 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001026 }
1027
Jozef Kolek1904fa22014-11-24 14:25:53 +00001028 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1029 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001030 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001031 }
1032
Zoran Jovanovic41688672015-02-10 16:36:20 +00001033 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1034 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001035 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001036 }
1037
Simon Atanasyan852dd832018-09-19 18:46:21 +00001038 void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
1039 assert(N == 1 && "Invalid number of operands!");
1040 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1041 }
1042
1043 void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
1044 unsigned N) const {
1045 assert(N == 1 && "Invalid number of operands!");
1046 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
1047 }
1048
Daniel Sanders21bce302014-04-01 12:35:23 +00001049 /// Render the operand to an MCInst as a GPR64
1050 /// Asserts if the wrong number of operands are requested, or the operand
1051 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1053 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001054 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 }
1056
1057 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1058 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001059 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 }
1061
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001062 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
1064 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1065 }
1066
1067 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1070 }
1071
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001072 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001074 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 }
1076
1077 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001079 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001080 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001081 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001082 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001083 AsmParser.getParser().printError(
1084 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1085 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001086 }
1087
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001088 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1089 assert(N == 1 && "Invalid number of operands!");
1090 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1091 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1092 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1093 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1094 "registers");
1095 }
1096
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 }
1101
1102 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 }
1106
1107 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001109 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 }
1111
1112 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 }
1116
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001117 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
1119 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1120 }
1121
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001125 }
1126
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001127 void addCOP3AsmRegOperands(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(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001130 }
1131
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 void addACC64DSPAsmRegOperands(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(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 }
1136
1137 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 }
1141
1142 void addLO32DSPAsmRegOperands(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(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001145 }
1146
1147 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001149 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 }
1151
1152 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001154 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001155 }
1156
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001157 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001158 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001160 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001161 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001162 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001163 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001164 Inst.addOperand(MCOperand::createImm(Imm));
1165 }
1166
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001167 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001168 void addSImmOperands(MCInst &Inst, unsigned N) const {
1169 if (isImm() && !isConstantImm()) {
1170 addExpr(Inst, getImm());
1171 return;
1172 }
1173 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1174 }
1175
1176 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001177 void addUImmOperands(MCInst &Inst, unsigned N) const {
1178 if (isImm() && !isConstantImm()) {
1179 addExpr(Inst, getImm());
1180 return;
1181 }
1182 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1183 }
1184
Daniel Sanders78e89022016-03-11 11:37:50 +00001185 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1186 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 int64_t Imm = getConstantImm() - Offset;
1189 Imm = SignExtend64<Bits>(Imm);
1190 Imm += Offset;
1191 Imm += AdjustOffset;
1192 Inst.addOperand(MCOperand::createImm(Imm));
1193 }
1194
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001195 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001196 assert(N == 1 && "Invalid number of operands!");
1197 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001198 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001199 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001200
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001201 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001202 assert(N == 2 && "Invalid number of operands!");
1203
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001204 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1205 ? getMemBase()->getGPR64Reg()
1206 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001207
1208 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001209 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001210 }
1211
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001212 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1213 assert(N == 2 && "Invalid number of operands!");
1214
Jim Grosbache9119e42015-05-13 18:37:00 +00001215 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001216
1217 const MCExpr *Expr = getMemOff();
1218 addExpr(Inst, Expr);
1219 }
1220
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001221 void addRegListOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
1223
1224 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001225 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001226 }
1227
Craig Topper56c590a2014-04-29 07:58:02 +00001228 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001229 // As a special case until we sort out the definition of div/divu, accept
1230 // $0/$zero here so that MCK_ZERO works correctly.
1231 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001232 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001233
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001235 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001238 int64_t Res;
1239 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001241
Daniel Sanders52da7af2015-11-06 12:11:03 +00001242 bool isConstantImmz() const {
1243 return isConstantImm() && getConstantImm() == 0;
1244 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001245
Daniel Sandersea4f6532015-11-06 12:22:31 +00001246 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1247 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1248 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001249
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001250 template <unsigned Bits> bool isSImm() const {
1251 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1252 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001253
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001254 template <unsigned Bits> bool isUImm() const {
1255 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1256 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001257
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001258 template <unsigned Bits> bool isAnyImm() const {
1259 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1260 isUInt<Bits>(getConstantImm()))
1261 : isImm();
1262 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001263
Daniel Sanders78e89022016-03-11 11:37:50 +00001264 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1265 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001266 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001267
Hrvoje Varga46458d02016-02-25 12:53:29 +00001268 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1269 return isConstantImm() && getConstantImm() >= Bottom &&
1270 getConstantImm() <= Top;
1271 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001272
Craig Topper56c590a2014-04-29 07:58:02 +00001273 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001274 // Note: It's not possible to pretend that other operand kinds are tokens.
1275 // The matcher emitter checks tokens first.
1276 return Kind == k_Token;
1277 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001278
Craig Topper56c590a2014-04-29 07:58:02 +00001279 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001280
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001281 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001282 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001283 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001284
Simon Dardis4ccda502016-05-27 13:56:36 +00001285 // Allow relocation operators.
1286 // FIXME: This predicate and others need to look through binary expressions
1287 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001288 template <unsigned Bits, unsigned ShiftAmount = 0>
1289 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001290 if (!isMem())
1291 return false;
1292 if (!getMemBase()->isGPRAsmReg())
1293 return false;
1294 if (isa<MCTargetExpr>(getMemOff()) ||
1295 (isConstantMemOff() &&
1296 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1297 return true;
1298 MCValue Res;
1299 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1300 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001301 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001302
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001303 bool isMemWithPtrSizeOffset() const {
1304 if (!isMem())
1305 return false;
1306 if (!getMemBase()->isGPRAsmReg())
1307 return false;
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00001308 const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001309 if (isa<MCTargetExpr>(getMemOff()) ||
1310 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1311 return true;
1312 MCValue Res;
1313 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1314 return IsReloc && isIntN(PtrBits, Res.getConstant());
1315 }
1316
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001317 bool isMemWithGRPMM16Base() const {
1318 return isMem() && getMemBase()->isMM16AsmReg();
1319 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001320
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001321 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1322 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1323 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1324 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001325
Jozef Kolek12c69822014-12-23 16:16:33 +00001326 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1327 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1328 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1329 && (getMemBase()->getGPR32Reg() == Mips::SP);
1330 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001331
Daniel Sanderse473dc92016-05-09 13:38:25 +00001332 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1333 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1334 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1335 && (getMemBase()->getGPR32Reg() == Mips::GP);
1336 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001337
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001338 template <unsigned Bits, unsigned ShiftLeftAmount>
1339 bool isScaledUImm() const {
1340 return isConstantImm() &&
1341 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001342 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001343
Daniel Sanders97297772016-03-22 14:40:00 +00001344 template <unsigned Bits, unsigned ShiftLeftAmount>
1345 bool isScaledSImm() const {
Simon Atanasyan478220f2018-05-24 07:36:00 +00001346 if (isConstantImm() &&
1347 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001348 return true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00001349 // Operand can also be a symbol or symbol plus
1350 // offset in case of relocations.
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001351 if (Kind != k_Immediate)
1352 return false;
1353 MCValue Res;
1354 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1355 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001356 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001357
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001358 bool isRegList16() const {
1359 if (!isRegList())
1360 return false;
1361
1362 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001363 if (Size < 2 || Size > 5)
1364 return false;
1365
1366 unsigned R0 = RegList.List->front();
1367 unsigned R1 = RegList.List->back();
1368 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1369 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001370 return false;
1371
1372 int PrevReg = *RegList.List->begin();
1373 for (int i = 1; i < Size - 1; i++) {
1374 int Reg = (*(RegList.List))[i];
1375 if ( Reg != PrevReg + 1)
1376 return false;
1377 PrevReg = Reg;
1378 }
1379
1380 return true;
1381 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001382
Vladimir Medic2b953d02013-10-01 09:48:56 +00001383 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001384
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001385 bool isLSAImm() const {
1386 if (!isConstantImm())
1387 return false;
1388 int64_t Val = getConstantImm();
1389 return 1 <= Val && Val <= 4;
1390 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001391
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001392 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001393
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001394 StringRef getToken() const {
1395 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001396 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001397 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001398
Craig Topper56c590a2014-04-29 07:58:02 +00001399 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001400 // As a special case until we sort out the definition of div/divu, accept
1401 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001402 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1403 RegIdx.Kind & RegKind_GPR)
1404 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001405
Daniel Sanders976d9382016-07-05 13:38:40 +00001406 llvm_unreachable("Invalid access!");
1407 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001408 }
1409
Jack Carterb4dbc172012-09-05 23:34:03 +00001410 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001411 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001412 return Imm.Val;
1413 }
1414
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 int64_t getConstantImm() const {
1416 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001417 int64_t Value = 0;
1418 (void)Val->evaluateAsAbsolute(Value);
1419 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001420 }
1421
1422 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001423 assert((Kind == k_Memory) && "Invalid access!");
1424 return Mem.Base;
1425 }
1426
1427 const MCExpr *getMemOff() const {
1428 assert((Kind == k_Memory) && "Invalid access!");
1429 return Mem.Off;
1430 }
1431
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001432 int64_t getConstantMemOff() const {
1433 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1434 }
1435
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001436 const SmallVectorImpl<unsigned> &getRegList() const {
1437 assert((Kind == k_RegList) && "Invalid access!");
1438 return *(RegList.List);
1439 }
1440
David Blaikie960ea3f2014-06-08 16:18:35 +00001441 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1442 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001443 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001444 Op->Tok.Data = Str.data();
1445 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001446 Op->StartLoc = S;
1447 Op->EndLoc = S;
1448 return Op;
1449 }
1450
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001451 /// Create a numeric register (e.g. $1). The exact register remains
1452 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001453 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001454 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1455 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001456 LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001457 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001458 }
1459
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001460 /// Create a register that is definitely a GPR.
1461 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001462 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001463 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1464 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1465 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001466 }
1467
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001468 /// Create a register that is definitely a FGR.
1469 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001470 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001471 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1472 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1473 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001474 }
1475
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001476 /// Create a register that is definitely a HWReg.
1477 /// This is typically only used for named registers such as $hwr_cpunum.
1478 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001479 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001480 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001481 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001482 }
1483
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001484 /// Create a register that is definitely an FCC.
1485 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001486 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001487 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1488 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1489 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001490 }
1491
1492 /// Create a register that is definitely an ACC.
1493 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001494 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001495 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1496 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1497 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001498 }
1499
1500 /// Create a register that is definitely an MSA128.
1501 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001502 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001503 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1504 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1505 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001506 }
1507
1508 /// Create a register that is definitely an MSACtrl.
1509 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001510 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001511 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1512 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1513 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001514 }
1515
David Blaikie960ea3f2014-06-08 16:18:35 +00001516 static std::unique_ptr<MipsOperand>
1517 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001518 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001519 Op->Imm.Val = Val;
1520 Op->StartLoc = S;
1521 Op->EndLoc = E;
1522 return Op;
1523 }
1524
David Blaikie960ea3f2014-06-08 16:18:35 +00001525 static std::unique_ptr<MipsOperand>
1526 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1527 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001528 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001529 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001530 Op->Mem.Off = Off;
1531 Op->StartLoc = S;
1532 Op->EndLoc = E;
1533 return Op;
1534 }
1535
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001536 static std::unique_ptr<MipsOperand>
1537 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1538 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001539 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001540
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001541 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001542 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001543 Op->StartLoc = StartLoc;
1544 Op->EndLoc = EndLoc;
1545 return Op;
1546 }
1547
Simon Dardis509da1a2017-02-13 16:06:48 +00001548 bool isGPRZeroAsmReg() const {
1549 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1550 }
1551
1552 bool isGPRNonZeroAsmReg() const {
1553 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1554 RegIdx.Index <= 31;
1555 }
1556
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001557 bool isGPRAsmReg() const {
1558 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001559 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001560
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001561 bool isMM16AsmReg() const {
1562 if (!(isRegIdx() && RegIdx.Kind))
1563 return false;
1564 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1565 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001566
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001567 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001568 bool isMM16AsmRegZero() const {
1569 if (!(isRegIdx() && RegIdx.Kind))
1570 return false;
1571 return (RegIdx.Index == 0 ||
1572 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1573 RegIdx.Index == 17);
1574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001575
Zoran Jovanovic41688672015-02-10 16:36:20 +00001576 bool isMM16AsmRegMoveP() const {
1577 if (!(isRegIdx() && RegIdx.Kind))
1578 return false;
1579 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1580 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1581 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001582
Simon Atanasyan852dd832018-09-19 18:46:21 +00001583 bool isMM16AsmRegMovePPairFirst() const {
1584 if (!(isRegIdx() && RegIdx.Kind))
1585 return false;
1586 return RegIdx.Index >= 4 && RegIdx.Index <= 6;
1587 }
1588
1589 bool isMM16AsmRegMovePPairSecond() const {
1590 if (!(isRegIdx() && RegIdx.Kind))
1591 return false;
1592 return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
1593 (RegIdx.Index >= 5 && RegIdx.Index <= 7));
1594 }
1595
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001596 bool isFGRAsmReg() const {
1597 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1598 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001599 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001600
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001601 bool isStrictlyFGRAsmReg() const {
1602 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1603 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1604 }
1605
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001606 bool isHWRegsAsmReg() const {
1607 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001608 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001609
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001610 bool isCCRAsmReg() const {
1611 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001612 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001613
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001614 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001615 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1616 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001617 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001618 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001619
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001620 bool isACCAsmReg() const {
1621 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001622 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001623
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001624 bool isCOP0AsmReg() const {
1625 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1626 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001627
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001628 bool isCOP2AsmReg() const {
1629 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001630 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001631
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001632 bool isCOP3AsmReg() const {
1633 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1634 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001635
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001636 bool isMSA128AsmReg() const {
1637 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001638 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001639
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001640 bool isMSACtrlAsmReg() const {
1641 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001642 }
1643
Jack Carterb4dbc172012-09-05 23:34:03 +00001644 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001645 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001646 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001647 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001648
Craig Topper56c590a2014-04-29 07:58:02 +00001649 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001650 switch (Kind) {
1651 case k_Immediate:
1652 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001653 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001654 OS << ">";
1655 break;
1656 case k_Memory:
1657 OS << "Mem<";
1658 Mem.Base->print(OS);
1659 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001660 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001661 OS << ">";
1662 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001663 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001664 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1665 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001666 break;
1667 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001668 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001670 case k_RegList:
1671 OS << "RegList< ";
1672 for (auto Reg : (*RegList.List))
1673 OS << Reg << " ";
1674 OS << ">";
1675 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001676 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001677 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001678
1679 bool isValidForTie(const MipsOperand &Other) const {
1680 if (Kind != Other.Kind)
1681 return false;
1682
1683 switch (Kind) {
1684 default:
1685 llvm_unreachable("Unexpected kind");
1686 return false;
1687 case k_RegisterIndex: {
1688 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1689 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1690 return Token == OtherToken;
1691 }
1692 }
1693 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001694}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001695
1696} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001697
Jack Carter9e65aa32013-03-22 00:05:30 +00001698namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001699
Jack Carter9e65aa32013-03-22 00:05:30 +00001700extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001701
1702} // end namespace llvm
1703
Jack Carter9e65aa32013-03-22 00:05:30 +00001704static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1705 return MipsInsts[Opcode];
1706}
1707
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001708static bool hasShortDelaySlot(unsigned Opcode) {
1709 switch (Opcode) {
1710 case Mips::JALS_MM:
1711 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001712 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001713 case Mips::BGEZALS_MM:
1714 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001715 return true;
1716 default:
1717 return false;
1718 }
1719}
1720
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001721static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1722 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1723 return &SRExpr->getSymbol();
1724 }
1725
1726 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1727 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1728 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1729
1730 if (LHSSym)
1731 return LHSSym;
1732
1733 if (RHSSym)
1734 return RHSSym;
1735
1736 return nullptr;
1737 }
1738
1739 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1740 return getSingleMCSymbol(UExpr->getSubExpr());
1741
1742 return nullptr;
1743}
1744
1745static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1746 if (isa<MCSymbolRefExpr>(Expr))
1747 return 1;
1748
1749 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1750 return countMCSymbolRefExpr(BExpr->getLHS()) +
1751 countMCSymbolRefExpr(BExpr->getRHS());
1752
1753 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1754 return countMCSymbolRefExpr(UExpr->getSubExpr());
1755
1756 return 0;
1757}
1758
Jack Carter9e65aa32013-03-22 00:05:30 +00001759bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001760 MCStreamer &Out,
1761 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001762 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001763 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001764 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001765
Jack Carter9e65aa32013-03-22 00:05:30 +00001766 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001767
1768 if (MCID.isBranch() || MCID.isCall()) {
1769 const unsigned Opcode = Inst.getOpcode();
1770 MCOperand Offset;
1771
1772 switch (Opcode) {
1773 default:
1774 break;
Kai Nackee0245392015-01-27 19:11:28 +00001775 case Mips::BBIT0:
1776 case Mips::BBIT032:
1777 case Mips::BBIT1:
1778 case Mips::BBIT132:
1779 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001780 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001781
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001782 case Mips::BEQ:
1783 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001784 case Mips::BEQ_MM:
1785 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001786 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001787 Offset = Inst.getOperand(2);
1788 if (!Offset.isImm())
1789 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001790 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001791 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001792 if (OffsetToAlignment(Offset.getImm(),
1793 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001794 return Error(IDLoc, "branch to misaligned address");
1795 break;
1796 case Mips::BGEZ:
1797 case Mips::BGTZ:
1798 case Mips::BLEZ:
1799 case Mips::BLTZ:
1800 case Mips::BGEZAL:
1801 case Mips::BLTZAL:
1802 case Mips::BC1F:
1803 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804 case Mips::BGEZ_MM:
1805 case Mips::BGTZ_MM:
1806 case Mips::BLEZ_MM:
1807 case Mips::BLTZ_MM:
1808 case Mips::BGEZAL_MM:
1809 case Mips::BLTZAL_MM:
1810 case Mips::BC1F_MM:
1811 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001812 case Mips::BC1EQZC_MMR6:
1813 case Mips::BC1NEZC_MMR6:
1814 case Mips::BC2EQZC_MMR6:
1815 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001816 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001817 Offset = Inst.getOperand(1);
1818 if (!Offset.isImm())
1819 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001820 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001821 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001822 if (OffsetToAlignment(Offset.getImm(),
1823 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001824 return Error(IDLoc, "branch to misaligned address");
1825 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001826 case Mips::BGEC: case Mips::BGEC_MMR6:
1827 case Mips::BLTC: case Mips::BLTC_MMR6:
1828 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1829 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1830 case Mips::BEQC: case Mips::BEQC_MMR6:
1831 case Mips::BNEC: case Mips::BNEC_MMR6:
1832 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1833 Offset = Inst.getOperand(2);
1834 if (!Offset.isImm())
1835 break; // We'll deal with this situation later on when applying fixups.
1836 if (!isIntN(18, Offset.getImm()))
1837 return Error(IDLoc, "branch target out of range");
1838 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1839 return Error(IDLoc, "branch to misaligned address");
1840 break;
1841 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1842 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1843 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1844 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1845 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1846 Offset = Inst.getOperand(1);
1847 if (!Offset.isImm())
1848 break; // We'll deal with this situation later on when applying fixups.
1849 if (!isIntN(18, Offset.getImm()))
1850 return Error(IDLoc, "branch target out of range");
1851 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1852 return Error(IDLoc, "branch to misaligned address");
1853 break;
1854 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1855 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1856 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1857 Offset = Inst.getOperand(1);
1858 if (!Offset.isImm())
1859 break; // We'll deal with this situation later on when applying fixups.
1860 if (!isIntN(23, Offset.getImm()))
1861 return Error(IDLoc, "branch target out of range");
1862 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1863 return Error(IDLoc, "branch to misaligned address");
1864 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001865 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001866 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001867 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001868 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001869 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1870 Offset = Inst.getOperand(1);
1871 if (!Offset.isImm())
1872 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001873 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001874 return Error(IDLoc, "branch target out of range");
1875 if (OffsetToAlignment(Offset.getImm(), 2LL))
1876 return Error(IDLoc, "branch to misaligned address");
1877 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001878 }
1879 }
1880
Daniel Sandersa84989a2014-06-16 13:25:35 +00001881 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1882 // We still accept it but it is a normal nop.
1883 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1884 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1885 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1886 "nop instruction");
1887 }
1888
Kai Nackee0245392015-01-27 19:11:28 +00001889 if (hasCnMips()) {
1890 const unsigned Opcode = Inst.getOpcode();
1891 MCOperand Opnd;
1892 int Imm;
1893
1894 switch (Opcode) {
1895 default:
1896 break;
1897
1898 case Mips::BBIT0:
1899 case Mips::BBIT032:
1900 case Mips::BBIT1:
1901 case Mips::BBIT132:
1902 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1903 // The offset is handled above
1904 Opnd = Inst.getOperand(1);
1905 if (!Opnd.isImm())
1906 return Error(IDLoc, "expected immediate operand kind");
1907 Imm = Opnd.getImm();
1908 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1909 Opcode == Mips::BBIT1 ? 63 : 31))
1910 return Error(IDLoc, "immediate operand value out of range");
1911 if (Imm > 31) {
1912 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1913 : Mips::BBIT132);
1914 Inst.getOperand(1).setImm(Imm - 32);
1915 }
1916 break;
1917
Kai Nackee0245392015-01-27 19:11:28 +00001918 case Mips::SEQi:
1919 case Mips::SNEi:
1920 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1921 Opnd = Inst.getOperand(2);
1922 if (!Opnd.isImm())
1923 return Error(IDLoc, "expected immediate operand kind");
1924 Imm = Opnd.getImm();
1925 if (!isInt<10>(Imm))
1926 return Error(IDLoc, "immediate operand value out of range");
1927 break;
1928 }
1929 }
1930
Simon Dardis509da1a2017-02-13 16:06:48 +00001931 // Warn on division by zero. We're checking here as all instructions get
1932 // processed here, not just the macros that need expansion.
1933 //
1934 // The MIPS backend models most of the divison instructions and macros as
1935 // three operand instructions. The pre-R6 divide instructions however have
1936 // two operands and explicitly define HI/LO as part of the instruction,
1937 // not in the operands.
1938 unsigned FirstOp = 1;
1939 unsigned SecondOp = 2;
1940 switch (Inst.getOpcode()) {
1941 default:
1942 break;
1943 case Mips::SDivIMacro:
1944 case Mips::UDivIMacro:
1945 case Mips::DSDivIMacro:
1946 case Mips::DUDivIMacro:
1947 if (Inst.getOperand(2).getImm() == 0) {
1948 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1949 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1950 Warning(IDLoc, "dividing zero by zero");
1951 else
1952 Warning(IDLoc, "division by zero");
1953 }
1954 break;
1955 case Mips::DSDIV:
1956 case Mips::SDIV:
1957 case Mips::UDIV:
1958 case Mips::DUDIV:
1959 case Mips::UDIV_MM:
1960 case Mips::SDIV_MM:
1961 FirstOp = 0;
1962 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001963 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001964 case Mips::SDivMacro:
1965 case Mips::DSDivMacro:
1966 case Mips::UDivMacro:
1967 case Mips::DUDivMacro:
1968 case Mips::DIV:
1969 case Mips::DIVU:
1970 case Mips::DDIV:
1971 case Mips::DDIVU:
1972 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001973 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001974 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1975 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1976 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1977 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1978 Warning(IDLoc, "dividing zero by zero");
1979 else
1980 Warning(IDLoc, "division by zero");
1981 }
1982 break;
1983 }
1984
Simon Atanasyan50485142016-12-12 17:40:26 +00001985 // For PIC code convert unconditional jump to unconditional branch.
1986 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1987 inPicMode()) {
1988 MCInst BInst;
1989 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1990 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1991 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1992 BInst.addOperand(Inst.getOperand(0));
1993 Inst = BInst;
1994 }
1995
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001996 // This expansion is not in a function called by tryExpandInstruction()
1997 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001998 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1999 inPicMode()) {
2000 warnIfNoMacro(IDLoc);
2001
2002 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2003
2004 // We can do this expansion if there's only 1 symbol in the argument
2005 // expression.
2006 if (countMCSymbolRefExpr(JalExpr) > 1)
2007 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2008
2009 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002010 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002011 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2012
2013 // FIXME: Add support for label+offset operands (currently causes an error).
2014 // FIXME: Add support for forward-declared local symbols.
2015 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002016 if (JalSym->isInSection() || JalSym->isTemporary() ||
Simon Atanasyan478220f2018-05-24 07:36:00 +00002017 (JalSym->isELF() &&
2018 cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002019 if (isABI_O32()) {
2020 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002021 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002022 // R_(MICRO)MIPS_GOT16 label
2023 // addiu $25, $25, 0
2024 // R_(MICRO)MIPS_LO16 label
2025 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002026 const MCExpr *Got16RelocExpr =
2027 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2028 const MCExpr *Lo16RelocExpr =
2029 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002030
Daniel Sandersa736b372016-04-29 13:33:12 +00002031 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2032 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2033 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2034 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002035 } else if (isABI_N32() || isABI_N64()) {
2036 // If it's a local symbol and the N32/N64 ABIs are being used,
2037 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002038 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002039 // R_(MICRO)MIPS_GOT_DISP label
2040 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002041 const MCExpr *GotDispRelocExpr =
2042 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002043
Daniel Sandersa736b372016-04-29 13:33:12 +00002044 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2045 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2046 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002047 }
2048 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002049 // If it's an external/weak symbol, we expand to:
2050 // lw/ld $25, 0($gp)
2051 // R_(MICRO)MIPS_CALL16 label
2052 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002053 const MCExpr *Call16RelocExpr =
2054 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002055
Daniel Sandersa736b372016-04-29 13:33:12 +00002056 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2057 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002058 }
2059
2060 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002061 if (IsCpRestoreSet && inMicroMipsMode())
2062 JalrInst.setOpcode(Mips::JALRS_MM);
2063 else
2064 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002065 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2066 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2067
2068 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2069 // This relocation is supposed to be an optimization hint for the linker
2070 // and is not necessary for correctness.
2071
2072 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002073 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002074 }
2075
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002076 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2077 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002078 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002079 // reference or immediate we may have to expand instructions.
2080 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002081 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002082 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2083 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002084 MCOperand &Op = Inst.getOperand(i);
2085 if (Op.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00002086 int64_t MemOffset = Op.getImm();
Jack Carter9e65aa32013-03-22 00:05:30 +00002087 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 // Offset can't exceed 16bit value.
Simon Atanasyana1882672018-05-24 07:36:11 +00002089 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002090 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002091 }
2092 } else if (Op.isExpr()) {
2093 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002094 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002095 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002096 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002097 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 // Expand symbol.
Simon Atanasyana1882672018-05-24 07:36:11 +00002099 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002100 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002101 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002102 } else if (!isEvaluated(Expr)) {
Simon Atanasyana1882672018-05-24 07:36:11 +00002103 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
Nirav Dave2364748a2016-09-16 18:30:20 +00002104 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002105 }
2106 }
2107 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002108 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002109 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002110
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002111 if (inMicroMipsMode()) {
Simon Dardis6a319922018-05-25 16:15:48 +00002112 if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002113 // Try to create 16-bit GP relative load instruction.
2114 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2115 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2116 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2117 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2118 MCOperand &Op = Inst.getOperand(i);
2119 if (Op.isImm()) {
2120 int MemOffset = Op.getImm();
2121 MCOperand &DstReg = Inst.getOperand(0);
2122 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002123 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002124 getContext().getRegisterInfo()->getRegClass(
2125 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002126 (BaseReg.getReg() == Mips::GP ||
2127 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002128
Daniel Sandersa736b372016-04-29 13:33:12 +00002129 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2130 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002131 return false;
2132 }
2133 }
2134 }
2135 } // for
2136 } // if load
2137
2138 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2139
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002140 MCOperand Opnd;
2141 int Imm;
2142
2143 switch (Inst.getOpcode()) {
2144 default:
2145 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002146 case Mips::ADDIUSP_MM:
2147 Opnd = Inst.getOperand(0);
2148 if (!Opnd.isImm())
2149 return Error(IDLoc, "expected immediate operand kind");
2150 Imm = Opnd.getImm();
2151 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2152 Imm % 4 != 0)
2153 return Error(IDLoc, "immediate operand value out of range");
2154 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002155 case Mips::SLL16_MM:
2156 case Mips::SRL16_MM:
2157 Opnd = Inst.getOperand(2);
2158 if (!Opnd.isImm())
2159 return Error(IDLoc, "expected immediate operand kind");
2160 Imm = Opnd.getImm();
2161 if (Imm < 1 || Imm > 8)
2162 return Error(IDLoc, "immediate operand value out of range");
2163 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002164 case Mips::LI16_MM:
2165 Opnd = Inst.getOperand(1);
2166 if (!Opnd.isImm())
2167 return Error(IDLoc, "expected immediate operand kind");
2168 Imm = Opnd.getImm();
2169 if (Imm < -1 || Imm > 126)
2170 return Error(IDLoc, "immediate operand value out of range");
2171 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002172 case Mips::ADDIUR2_MM:
2173 Opnd = Inst.getOperand(2);
2174 if (!Opnd.isImm())
2175 return Error(IDLoc, "expected immediate operand kind");
2176 Imm = Opnd.getImm();
2177 if (!(Imm == 1 || Imm == -1 ||
2178 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2179 return Error(IDLoc, "immediate operand value out of range");
2180 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002181 case Mips::ANDI16_MM:
2182 Opnd = Inst.getOperand(2);
2183 if (!Opnd.isImm())
2184 return Error(IDLoc, "expected immediate operand kind");
2185 Imm = Opnd.getImm();
2186 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2187 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2188 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2189 return Error(IDLoc, "immediate operand value out of range");
2190 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002191 case Mips::LBU16_MM:
2192 Opnd = Inst.getOperand(2);
2193 if (!Opnd.isImm())
2194 return Error(IDLoc, "expected immediate operand kind");
2195 Imm = Opnd.getImm();
2196 if (Imm < -1 || Imm > 14)
2197 return Error(IDLoc, "immediate operand value out of range");
2198 break;
2199 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002200 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002201 Opnd = Inst.getOperand(2);
2202 if (!Opnd.isImm())
2203 return Error(IDLoc, "expected immediate operand kind");
2204 Imm = Opnd.getImm();
2205 if (Imm < 0 || Imm > 15)
2206 return Error(IDLoc, "immediate operand value out of range");
2207 break;
2208 case Mips::LHU16_MM:
2209 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002210 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002211 Opnd = Inst.getOperand(2);
2212 if (!Opnd.isImm())
2213 return Error(IDLoc, "expected immediate operand kind");
2214 Imm = Opnd.getImm();
2215 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2216 return Error(IDLoc, "immediate operand value out of range");
2217 break;
2218 case Mips::LW16_MM:
2219 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002220 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002221 Opnd = Inst.getOperand(2);
2222 if (!Opnd.isImm())
2223 return Error(IDLoc, "expected immediate operand kind");
2224 Imm = Opnd.getImm();
2225 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2226 return Error(IDLoc, "immediate operand value out of range");
2227 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002228 case Mips::ADDIUPC_MM:
Simon Dardis6a319922018-05-25 16:15:48 +00002229 Opnd = Inst.getOperand(1);
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002230 if (!Opnd.isImm())
2231 return Error(IDLoc, "expected immediate operand kind");
Simon Dardis6a319922018-05-25 16:15:48 +00002232 Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002233 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002234 return Error(IDLoc, "immediate operand value out of range");
2235 break;
Simon Dardis6a319922018-05-25 16:15:48 +00002236 case Mips::LWP_MM:
2237 case Mips::SWP_MM:
2238 if (Inst.getOperand(0).getReg() == Mips::RA)
2239 return Error(IDLoc, "invalid operand for instruction");
2240 break;
Simon Atanasyan852dd832018-09-19 18:46:21 +00002241 case Mips::MOVEP_MM:
2242 case Mips::MOVEP_MMR6: {
2243 unsigned R0 = Inst.getOperand(0).getReg();
2244 unsigned R1 = Inst.getOperand(1).getReg();
2245 bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
2246 (R0 == Mips::A1 && R1 == Mips::A3) ||
2247 (R0 == Mips::A2 && R1 == Mips::A3) ||
2248 (R0 == Mips::A0 && R1 == Mips::S5) ||
2249 (R0 == Mips::A0 && R1 == Mips::S6) ||
2250 (R0 == Mips::A0 && R1 == Mips::A1) ||
2251 (R0 == Mips::A0 && R1 == Mips::A2) ||
2252 (R0 == Mips::A0 && R1 == Mips::A3));
2253 if (!RegPair)
2254 return Error(IDLoc, "invalid operand for instruction");
2255 break;
2256 }
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002257 }
2258 }
2259
Daniel Sandersd8c07762016-04-18 12:35:36 +00002260 bool FillDelaySlot =
2261 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2262 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002263 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002264
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002265 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002266 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002267 switch (ExpandResult) {
2268 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002269 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002270 break;
2271 case MER_Success:
2272 break;
2273 case MER_Fail:
2274 return true;
2275 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002276
Daniel Sanderscda908a2016-05-16 09:10:13 +00002277 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2278 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002279 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002280 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002281 TOut.updateABIInfo(*this);
2282 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002283
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002284 // If this instruction has a delay slot and .set reorder is active,
2285 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002286 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002287 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2288 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002289 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002290
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002291 if ((Inst.getOpcode() == Mips::JalOneReg ||
2292 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2293 isPicAndNotNxxAbi()) {
2294 if (IsCpRestoreSet) {
2295 // We need a NOP between the JALR and the LW:
2296 // If .set reorder has been used, we've already emitted a NOP.
2297 // If .set noreorder has been used, we need to emit a NOP at this point.
2298 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002299 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2300 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002301
2302 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002303 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002304 } else
2305 Warning(IDLoc, "no .cprestore used in PIC mode");
2306 }
2307
Jack Carter9e65aa32013-03-22 00:05:30 +00002308 return false;
2309}
2310
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002311MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002312MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2313 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002314 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002315 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002316 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002317 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002318 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002319 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002320 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002321 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002322 case Mips::LoadAddrImm64:
2323 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2324 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2325 "expected immediate operand kind");
2326
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002327 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2328 Inst.getOperand(1),
2329 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002330 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002331 ? MER_Fail
2332 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002333 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002334 case Mips::LoadAddrReg64:
2335 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2336 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2337 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2338 "expected immediate operand kind");
2339
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002340 return expandLoadAddress(Inst.getOperand(0).getReg(),
2341 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2342 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002343 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002344 ? MER_Fail
2345 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002346 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002347 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002348 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2349 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002350 case Mips::SWM_MM:
2351 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002352 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2353 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002354 case Mips::JalOneReg:
2355 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002356 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002357 case Mips::BneImm:
2358 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002359 case Mips::BEQLImmMacro:
2360 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002361 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002362 case Mips::BLT:
2363 case Mips::BLE:
2364 case Mips::BGE:
2365 case Mips::BGT:
2366 case Mips::BLTU:
2367 case Mips::BLEU:
2368 case Mips::BGEU:
2369 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002370 case Mips::BLTL:
2371 case Mips::BLEL:
2372 case Mips::BGEL:
2373 case Mips::BGTL:
2374 case Mips::BLTUL:
2375 case Mips::BLEUL:
2376 case Mips::BGEUL:
2377 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002378 case Mips::BLTImmMacro:
2379 case Mips::BLEImmMacro:
2380 case Mips::BGEImmMacro:
2381 case Mips::BGTImmMacro:
2382 case Mips::BLTUImmMacro:
2383 case Mips::BLEUImmMacro:
2384 case Mips::BGEUImmMacro:
2385 case Mips::BGTUImmMacro:
2386 case Mips::BLTLImmMacro:
2387 case Mips::BLELImmMacro:
2388 case Mips::BGELImmMacro:
2389 case Mips::BGTLImmMacro:
2390 case Mips::BLTULImmMacro:
2391 case Mips::BLEULImmMacro:
2392 case Mips::BGEULImmMacro:
2393 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002394 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002395 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002396 case Mips::SDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002397 case Mips::SRemMacro:
2398 case Mips::SRemIMacro:
2399 return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2400 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002401 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002402 case Mips::DSDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002403 case Mips::DSRemMacro:
2404 case Mips::DSRemIMacro:
2405 return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2406 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002407 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002408 case Mips::UDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002409 case Mips::URemMacro:
2410 case Mips::URemIMacro:
2411 return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2412 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002413 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002414 case Mips::DUDivIMacro:
Stefan Maksimovic0a239982018-07-09 13:06:44 +00002415 case Mips::DURemMacro:
2416 case Mips::DURemIMacro:
2417 return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2418 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002419 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002420 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2421 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002422 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002423 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002424 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002425 case Mips::PseudoTRUNC_W_D:
2426 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2427 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002428
2429 case Mips::LoadImmSingleGPR:
2430 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2431 ? MER_Fail
2432 : MER_Success;
2433 case Mips::LoadImmSingleFGR:
2434 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2435 ? MER_Fail
2436 : MER_Success;
2437 case Mips::LoadImmDoubleGPR:
2438 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2439 ? MER_Fail
2440 : MER_Success;
2441 case Mips::LoadImmDoubleFGR:
2442 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2443 ? MER_Fail
2444 : MER_Success;
2445 case Mips::LoadImmDoubleFGR_32:
2446 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2447 ? MER_Fail
2448 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002449 case Mips::Ulh:
2450 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2451 case Mips::Ulhu:
2452 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002453 case Mips::Ush:
2454 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002455 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002456 case Mips::Usw:
2457 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002458 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002459 case Mips::NORImm64:
2460 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2461 case Mips::SLTImm64:
2462 if (isInt<16>(Inst.getOperand(2).getImm())) {
2463 Inst.setOpcode(Mips::SLTi64);
2464 return MER_NotAMacro;
2465 }
2466 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2467 case Mips::SLTUImm64:
2468 if (isInt<16>(Inst.getOperand(2).getImm())) {
2469 Inst.setOpcode(Mips::SLTiu64);
2470 return MER_NotAMacro;
2471 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002472 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002473 case Mips::ADDi: case Mips::ADDi_MM:
2474 case Mips::ADDiu: case Mips::ADDiu_MM:
2475 case Mips::SLTi: case Mips::SLTi_MM:
2476 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002477 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2478 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2479 int64_t ImmValue = Inst.getOperand(2).getImm();
2480 if (isInt<16>(ImmValue))
2481 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002482 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2483 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002484 }
2485 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002486 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2487 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2488 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002489 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2490 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2491 int64_t ImmValue = Inst.getOperand(2).getImm();
2492 if (isUInt<16>(ImmValue))
2493 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002494 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2495 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002496 }
2497 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002498 case Mips::ROL:
2499 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002500 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002501 case Mips::ROLImm:
2502 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002503 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002504 case Mips::DROL:
2505 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002506 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002507 case Mips::DROLImm:
2508 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002509 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002510 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002511 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002512 case Mips::MULImmMacro:
2513 case Mips::DMULImmMacro:
2514 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2515 case Mips::MULOMacro:
2516 case Mips::DMULOMacro:
2517 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2518 case Mips::MULOUMacro:
2519 case Mips::DMULOUMacro:
2520 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2521 case Mips::DMULMacro:
2522 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002523 case Mips::LDMacro:
2524 case Mips::SDMacro:
2525 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2526 Inst.getOpcode() == Mips::LDMacro)
2527 ? MER_Fail
2528 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002529 case Mips::SEQMacro:
2530 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2531 case Mips::SEQIMacro:
2532 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002533 case Mips::MFTC0: case Mips::MTTC0:
2534 case Mips::MFTGPR: case Mips::MTTGPR:
2535 case Mips::MFTLO: case Mips::MTTLO:
2536 case Mips::MFTHI: case Mips::MTTHI:
2537 case Mips::MFTACX: case Mips::MTTACX:
2538 case Mips::MFTDSP: case Mips::MTTDSP:
2539 case Mips::MFTC1: case Mips::MTTC1:
2540 case Mips::MFTHC1: case Mips::MTTHC1:
2541 case Mips::CFTC1: case Mips::CTTC1:
2542 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 }
Jack Carter30a59822012-10-04 04:03:53 +00002544}
Jack Carter92995f12012-10-06 00:53:28 +00002545
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002546bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002547 MCStreamer &Out,
2548 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002549 MipsTargetStreamer &TOut = getTargetStreamer();
2550
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002551 // Create a JALR instruction which is going to replace the pseudo-JAL.
2552 MCInst JalrInst;
2553 JalrInst.setLoc(IDLoc);
2554 const MCOperand FirstRegOp = Inst.getOperand(0);
2555 const unsigned Opcode = Inst.getOpcode();
2556
2557 if (Opcode == Mips::JalOneReg) {
2558 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002559 if (IsCpRestoreSet && inMicroMipsMode()) {
2560 JalrInst.setOpcode(Mips::JALRS16_MM);
2561 JalrInst.addOperand(FirstRegOp);
2562 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002563 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002564 JalrInst.addOperand(FirstRegOp);
2565 } else {
2566 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002567 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002568 JalrInst.addOperand(FirstRegOp);
2569 }
2570 } else if (Opcode == Mips::JalTwoReg) {
2571 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002572 if (IsCpRestoreSet && inMicroMipsMode())
2573 JalrInst.setOpcode(Mips::JALRS_MM);
2574 else
2575 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002576 JalrInst.addOperand(FirstRegOp);
2577 const MCOperand SecondRegOp = Inst.getOperand(1);
2578 JalrInst.addOperand(SecondRegOp);
2579 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002580 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002581
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002582 // If .set reorder is active and branch instruction has a delay slot,
2583 // emit a NOP after it.
2584 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002585 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2586 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2587 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002588
2589 return false;
2590}
2591
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002592/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002593template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002594 unsigned BitNum = findFirstSet(x);
2595
2596 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2597}
2598
2599/// Load (or add) an immediate into a register.
2600///
2601/// @param ImmValue The immediate to load.
2602/// @param DstReg The register that will hold the immediate.
2603/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2604/// for a simple initialization.
2605/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2606/// @param IsAddress True if the immediate represents an address. False if it
2607/// is an integer.
2608/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002609bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002610 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002611 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2612 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002613 MipsTargetStreamer &TOut = getTargetStreamer();
2614
Toma Tabacu00e98672015-05-01 12:19:27 +00002615 if (!Is32BitImm && !isGP64bit()) {
2616 Error(IDLoc, "instruction requires a 64-bit architecture");
2617 return true;
2618 }
2619
Daniel Sanders03f9c012015-07-14 12:24:22 +00002620 if (Is32BitImm) {
2621 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2622 // Sign extend up to 64-bit so that the predicates match the hardware
2623 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2624 // true.
2625 ImmValue = SignExtend64<32>(ImmValue);
2626 } else {
2627 Error(IDLoc, "instruction requires a 32-bit immediate");
2628 return true;
2629 }
2630 }
2631
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002632 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2633 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2634
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002635 bool UseSrcReg = false;
2636 if (SrcReg != Mips::NoRegister)
2637 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002638
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002639 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002640 if (UseSrcReg &&
2641 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002642 // At this point we need AT to perform the expansions and we exit if it is
2643 // not available.
2644 unsigned ATReg = getATReg(IDLoc);
2645 if (!ATReg)
2646 return true;
2647 TmpReg = ATReg;
2648 }
2649
Daniel Sanders03f9c012015-07-14 12:24:22 +00002650 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002651 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002652 SrcReg = ZeroReg;
2653
2654 // This doesn't quite follow the usual ABI expectations for N32 but matches
2655 // traditional assembler behaviour. N32 would normally use addiu for both
2656 // integers and addresses.
2657 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002658 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002659 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002660 }
2661
Daniel Sandersa736b372016-04-29 13:33:12 +00002662 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002663 return false;
2664 }
2665
2666 if (isUInt<16>(ImmValue)) {
2667 unsigned TmpReg = DstReg;
2668 if (SrcReg == DstReg) {
2669 TmpReg = getATReg(IDLoc);
2670 if (!TmpReg)
2671 return true;
2672 }
2673
Daniel Sandersa736b372016-04-29 13:33:12 +00002674 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002675 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002676 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002677 return false;
2678 }
2679
2680 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002681 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002682
Toma Tabacu79588102015-04-29 10:19:56 +00002683 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2684 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002685 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002686 // Traditional behaviour seems to special case this particular value. It's
2687 // not clear why other masks are handled differently.
2688 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002689 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2690 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002691 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002692 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002693 return false;
2694 }
2695
2696 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002697 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002698 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2699 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002700 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002701 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002702 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002703 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002704 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002705 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002706
Daniel Sandersa736b372016-04-29 13:33:12 +00002707 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002708 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002709 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002710 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002711 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002712 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002713 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002714
2715 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2716 if (Is32BitImm) {
2717 Error(IDLoc, "instruction requires a 32-bit immediate");
2718 return true;
2719 }
2720
2721 // Traditionally, these immediates are shifted as little as possible and as
2722 // such we align the most significant bit to bit 15 of our temporary.
2723 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2724 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2725 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2726 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002727 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2728 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002729
2730 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002731 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002732
2733 return false;
2734 }
2735
2736 warnIfNoMacro(IDLoc);
2737
2738 // The remaining case is packed with a sequence of dsll and ori with zeros
2739 // being omitted and any neighbouring dsll's being coalesced.
2740 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2741
2742 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2743 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002744 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002745 return false;
2746
2747 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2748 // skip it and defer the shift to the next chunk.
2749 unsigned ShiftCarriedForwards = 16;
2750 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2751 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2752
2753 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002754 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2755 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002756 ShiftCarriedForwards = 0;
2757 }
2758
2759 ShiftCarriedForwards += 16;
2760 }
2761 ShiftCarriedForwards -= 16;
2762
2763 // Finish any remaining shifts left by trailing zeros.
2764 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002765 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002766
2767 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002768 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002769
Matheus Almeida3813d572014-06-19 14:39:14 +00002770 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002771}
Jack Carter92995f12012-10-06 00:53:28 +00002772
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002773bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002774 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002775 const MCOperand &ImmOp = Inst.getOperand(1);
2776 assert(ImmOp.isImm() && "expected immediate operand kind");
2777 const MCOperand &DstRegOp = Inst.getOperand(0);
2778 assert(DstRegOp.isReg() && "expected register operand kind");
2779
2780 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002781 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002782 return true;
2783
2784 return false;
2785}
2786
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002787bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2788 const MCOperand &Offset,
2789 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002790 MCStreamer &Out,
2791 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002792 // la can't produce a usable address when addresses are 64-bit.
2793 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2794 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2795 // We currently can't do this because we depend on the equality
2796 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2797 Error(IDLoc, "la used to load 64-bit address");
2798 // Continue as if we had 'dla' instead.
2799 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002800 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002801 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002802
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002803 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002804 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002805 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002806 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002807 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002808
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002809 if (!Offset.isImm())
2810 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002811 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002812
Scott Egerton24557012016-01-21 15:11:01 +00002813 if (!ABI.ArePtrs64bit()) {
2814 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2815 Is32BitAddress = true;
2816 }
2817
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002818 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002819 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002820}
2821
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002822bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2823 unsigned DstReg, unsigned SrcReg,
2824 bool Is32BitSym, SMLoc IDLoc,
2825 MCStreamer &Out,
2826 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002827 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002828 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002829 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002830 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002831
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002832 if (inPicMode() && ABI.IsO32()) {
2833 MCValue Res;
2834 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2835 Error(IDLoc, "expected relocatable expression");
2836 return true;
2837 }
2838 if (Res.getSymB() != nullptr) {
2839 Error(IDLoc, "expected relocatable expression with only one symbol");
2840 return true;
2841 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002842
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002843 // The case where the result register is $25 is somewhat special. If the
2844 // symbol in the final relocation is external and not modified with a
2845 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2846 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002847 Res.getConstant() == 0 &&
2848 !(Res.getSymA()->getSymbol().isInSection() ||
2849 Res.getSymA()->getSymbol().isTemporary() ||
2850 (Res.getSymA()->getSymbol().isELF() &&
2851 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2852 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002853 const MCExpr *CallExpr =
2854 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2855 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2856 MCOperand::createExpr(CallExpr), IDLoc, STI);
2857 return false;
2858 }
2859
2860 // The remaining cases are:
2861 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2862 // >addiu $tmp, $tmp, %lo(offset)
2863 // >addiu $rd, $tmp, $rs
2864 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2865 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2866 // >addiu $rd, $tmp, $rs
2867 // The addiu's marked with a '>' may be omitted if they are redundant. If
2868 // this happens then the last instruction must use $rd as the result
2869 // register.
2870 const MipsMCExpr *GotExpr =
2871 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2872 const MCExpr *LoExpr = nullptr;
2873 if (Res.getSymA()->getSymbol().isInSection() ||
2874 Res.getSymA()->getSymbol().isTemporary())
2875 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2876 else if (Res.getConstant() != 0) {
2877 // External symbols fully resolve the symbol with just the %got(symbol)
2878 // but we must still account for any offset to the symbol for expressions
2879 // like symbol+8.
2880 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2881 }
2882
2883 unsigned TmpReg = DstReg;
2884 if (UseSrcReg &&
2885 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2886 SrcReg)) {
2887 // If $rs is the same as $rd, we need to use AT.
2888 // If it is not available we exit.
2889 unsigned ATReg = getATReg(IDLoc);
2890 if (!ATReg)
2891 return true;
2892 TmpReg = ATReg;
2893 }
2894
2895 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2896 MCOperand::createExpr(GotExpr), IDLoc, STI);
2897
2898 if (LoExpr)
2899 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2900 IDLoc, STI);
2901
2902 if (UseSrcReg)
2903 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2904
2905 return false;
2906 }
2907
Simon Dardisda96c432017-06-30 15:44:27 +00002908 if (inPicMode() && ABI.ArePtrs64bit()) {
2909 MCValue Res;
2910 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2911 Error(IDLoc, "expected relocatable expression");
2912 return true;
2913 }
2914 if (Res.getSymB() != nullptr) {
2915 Error(IDLoc, "expected relocatable expression with only one symbol");
2916 return true;
2917 }
2918
2919 // The case where the result register is $25 is somewhat special. If the
2920 // symbol in the final relocation is external and not modified with a
2921 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2922 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2923 Res.getConstant() == 0 &&
2924 !(Res.getSymA()->getSymbol().isInSection() ||
2925 Res.getSymA()->getSymbol().isTemporary() ||
2926 (Res.getSymA()->getSymbol().isELF() &&
2927 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2928 ELF::STB_LOCAL))) {
2929 const MCExpr *CallExpr =
2930 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2931 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2932 MCOperand::createExpr(CallExpr), IDLoc, STI);
2933 return false;
2934 }
2935
2936 // The remaining cases are:
2937 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2938 // >daddiu $tmp, $tmp, offset
2939 // >daddu $rd, $tmp, $rs
2940 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2941 // this happens then the last instruction must use $rd as the result
2942 // register.
2943 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2944 Res.getSymA(),
2945 getContext());
2946 const MCExpr *LoExpr = nullptr;
2947 if (Res.getConstant() != 0) {
2948 // Symbols fully resolve with just the %got_disp(symbol) but we
2949 // must still account for any offset to the symbol for
2950 // expressions like symbol+8.
2951 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2952
2953 // FIXME: Offsets greater than 16 bits are not yet implemented.
2954 // FIXME: The correct range is a 32-bit sign-extended number.
2955 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2956 Error(IDLoc, "macro instruction uses large offset, which is not "
2957 "currently supported");
2958 return true;
2959 }
2960 }
2961
2962 unsigned TmpReg = DstReg;
2963 if (UseSrcReg &&
2964 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2965 SrcReg)) {
2966 // If $rs is the same as $rd, we need to use AT.
2967 // If it is not available we exit.
2968 unsigned ATReg = getATReg(IDLoc);
2969 if (!ATReg)
2970 return true;
2971 TmpReg = ATReg;
2972 }
2973
2974 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2975 MCOperand::createExpr(GotExpr), IDLoc, STI);
2976
2977 if (LoExpr)
2978 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2979 IDLoc, STI);
2980
2981 if (UseSrcReg)
2982 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2983
2984 return false;
2985 }
2986
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002987 const MipsMCExpr *HiExpr =
2988 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2989 const MipsMCExpr *LoExpr =
2990 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002991
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002992 // This is the 64-bit symbol address expansion.
2993 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002994 // We need AT for the 64-bit expansion in the cases where the optional
2995 // source register is the destination register and for the superscalar
2996 // scheduled form.
2997 //
2998 // If it is not available we exit if the destination is the same as the
2999 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003000
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003001 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003002 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003003 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003004 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003005
Simon Dardis3aa8a902017-02-06 12:43:46 +00003006 bool RdRegIsRsReg =
3007 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3008
3009 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3010 unsigned ATReg = getATReg(IDLoc);
3011
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003012 // If $rs is the same as $rd:
3013 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3014 // daddiu $at, $at, %higher(sym)
3015 // dsll $at, $at, 16
3016 // daddiu $at, $at, %hi(sym)
3017 // dsll $at, $at, 16
3018 // daddiu $at, $at, %lo(sym)
3019 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003020 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3021 STI);
3022 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3023 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3024 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3025 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3026 IDLoc, STI);
3027 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3028 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3029 IDLoc, STI);
3030 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003031
3032 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003033 } else if (canUseATReg() && !RdRegIsRsReg) {
3034 unsigned ATReg = getATReg(IDLoc);
3035
3036 // If the $rs is different from $rd or if $rs isn't specified and we
3037 // have $at available:
3038 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3039 // lui $at, %hi(sym)
3040 // daddiu $rd, $rd, %higher(sym)
3041 // daddiu $at, $at, %lo(sym)
3042 // dsll32 $rd, $rd, 0
3043 // daddu $rd, $rd, $at
3044 // (daddu $rd, $rd, $rs)
3045 //
3046 // Which is preferred for superscalar issue.
3047 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3048 STI);
3049 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3050 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3051 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3052 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3053 IDLoc, STI);
3054 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3055 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3056 if (UseSrcReg)
3057 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3058
3059 return false;
3060 } else if (!canUseATReg() && !RdRegIsRsReg) {
3061 // Otherwise, synthesize the address in the destination register
3062 // serially:
3063 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3064 // daddiu $rd, $rd, %higher(sym)
3065 // dsll $rd, $rd, 16
3066 // daddiu $rd, $rd, %hi(sym)
3067 // dsll $rd, $rd, 16
3068 // daddiu $rd, $rd, %lo(sym)
3069 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3070 STI);
3071 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3072 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3073 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3074 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3075 MCOperand::createExpr(HiExpr), IDLoc, STI);
3076 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3077 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3078 MCOperand::createExpr(LoExpr), IDLoc, STI);
3079 if (UseSrcReg)
3080 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3081
3082 return false;
3083 } else {
3084 // We have a case where SrcReg == DstReg and we don't have $at
3085 // available. We can't expand this case, so error out appropriately.
3086 assert(SrcReg == DstReg && !canUseATReg() &&
3087 "Could have expanded dla but didn't?");
3088 reportParseError(IDLoc,
3089 "pseudo-instruction requires $at, which is not available");
3090 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003091 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003092 }
3093
3094 // And now, the 32-bit symbol address expansion:
3095 // If $rs is the same as $rd:
3096 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3097 // ori $at, $at, %lo(sym)
3098 // addu $rd, $at, $rd
3099 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3100 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3101 // ori $rd, $rd, %lo(sym)
3102 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003103 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003104 if (UseSrcReg &&
3105 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003106 // If $rs is the same as $rd, we need to use AT.
3107 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003108 unsigned ATReg = getATReg(IDLoc);
3109 if (!ATReg)
3110 return true;
3111 TmpReg = ATReg;
3112 }
3113
Daniel Sandersa736b372016-04-29 13:33:12 +00003114 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3115 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3116 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003117
Toma Tabacufb9d1252015-06-22 12:08:39 +00003118 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003119 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003120 else
Scott Egerton24557012016-01-21 15:11:01 +00003121 assert(
3122 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003123
Toma Tabacu674825c2015-06-16 12:16:24 +00003124 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003125}
3126
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003127// Each double-precision register DO-D15 overlaps with two of the single
3128// precision registers F0-F31. As an example, all of the following hold true:
3129// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3130static unsigned nextReg(unsigned Reg) {
3131 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3132 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3133 switch (Reg) {
3134 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3135 case Mips::ZERO: return Mips::AT;
3136 case Mips::AT: return Mips::V0;
3137 case Mips::V0: return Mips::V1;
3138 case Mips::V1: return Mips::A0;
3139 case Mips::A0: return Mips::A1;
3140 case Mips::A1: return Mips::A2;
3141 case Mips::A2: return Mips::A3;
3142 case Mips::A3: return Mips::T0;
3143 case Mips::T0: return Mips::T1;
3144 case Mips::T1: return Mips::T2;
3145 case Mips::T2: return Mips::T3;
3146 case Mips::T3: return Mips::T4;
3147 case Mips::T4: return Mips::T5;
3148 case Mips::T5: return Mips::T6;
3149 case Mips::T6: return Mips::T7;
3150 case Mips::T7: return Mips::S0;
3151 case Mips::S0: return Mips::S1;
3152 case Mips::S1: return Mips::S2;
3153 case Mips::S2: return Mips::S3;
3154 case Mips::S3: return Mips::S4;
3155 case Mips::S4: return Mips::S5;
3156 case Mips::S5: return Mips::S6;
3157 case Mips::S6: return Mips::S7;
3158 case Mips::S7: return Mips::T8;
3159 case Mips::T8: return Mips::T9;
3160 case Mips::T9: return Mips::K0;
3161 case Mips::K0: return Mips::K1;
3162 case Mips::K1: return Mips::GP;
3163 case Mips::GP: return Mips::SP;
3164 case Mips::SP: return Mips::FP;
3165 case Mips::FP: return Mips::RA;
3166 case Mips::RA: return Mips::ZERO;
3167 case Mips::D0: return Mips::F1;
3168 case Mips::D1: return Mips::F3;
3169 case Mips::D2: return Mips::F5;
3170 case Mips::D3: return Mips::F7;
3171 case Mips::D4: return Mips::F9;
3172 case Mips::D5: return Mips::F11;
3173 case Mips::D6: return Mips::F13;
3174 case Mips::D7: return Mips::F15;
3175 case Mips::D8: return Mips::F17;
3176 case Mips::D9: return Mips::F19;
3177 case Mips::D10: return Mips::F21;
3178 case Mips::D11: return Mips::F23;
3179 case Mips::D12: return Mips::F25;
3180 case Mips::D13: return Mips::F27;
3181 case Mips::D14: return Mips::F29;
3182 case Mips::D15: return Mips::F31;
3183 }
3184}
3185
3186// FIXME: This method is too general. In principle we should compute the number
3187// of instructions required to synthesize the immediate inline compared to
3188// synthesizing the address inline and relying on non .text sections.
3189// For static O32 and N32 this may yield a small benefit, for static N64 this is
3190// likely to yield a much larger benefit as we have to synthesize a 64bit
3191// address to load a 64 bit value.
3192bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3193 MCSymbol *Sym) {
3194 unsigned ATReg = getATReg(IDLoc);
3195 if (!ATReg)
3196 return true;
3197
3198 if(IsPicEnabled) {
3199 const MCExpr *GotSym =
3200 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3201 const MipsMCExpr *GotExpr =
3202 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3203
3204 if(isABI_O32() || isABI_N32()) {
3205 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3206 IDLoc, STI);
3207 } else { //isABI_N64()
3208 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3209 IDLoc, STI);
3210 }
3211 } else { //!IsPicEnabled
3212 const MCExpr *HiSym =
3213 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3214 const MipsMCExpr *HiExpr =
3215 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3216
3217 // FIXME: This is technically correct but gives a different result to gas,
3218 // but gas is incomplete there (it has a fixme noting it doesn't work with
3219 // 64-bit addresses).
3220 // FIXME: With -msym32 option, the address expansion for N64 should probably
3221 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3222 // symbol's value is considered sign extended.
3223 if(isABI_O32() || isABI_N32()) {
3224 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3225 } else { //isABI_N64()
3226 const MCExpr *HighestSym =
3227 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3228 const MipsMCExpr *HighestExpr =
3229 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3230 const MCExpr *HigherSym =
3231 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3232 const MipsMCExpr *HigherExpr =
3233 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3234
3235 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3236 STI);
3237 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3238 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3239 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3240 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3241 IDLoc, STI);
3242 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3243 }
3244 }
3245 return false;
3246}
3247
3248bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3249 bool Is64FPU, SMLoc IDLoc,
3250 MCStreamer &Out,
3251 const MCSubtargetInfo *STI) {
3252 MipsTargetStreamer &TOut = getTargetStreamer();
3253 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3254 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3255 "Invalid instruction operand.");
3256
3257 unsigned FirstReg = Inst.getOperand(0).getReg();
3258 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3259
3260 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3261 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3262 // exponent field), convert it to double (e.g. 1 to 1.0)
3263 if ((HiImmOp64 & 0x7ff00000) == 0) {
3264 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3265 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3266 }
3267
3268 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3269 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3270
3271 if (IsSingle) {
3272 // Conversion of a double in an uint64_t to a float in a uint32_t,
3273 // retaining the bit pattern of a float.
3274 uint32_t ImmOp32;
3275 double doubleImm = BitsToDouble(ImmOp64);
3276 float tmp_float = static_cast<float>(doubleImm);
3277 ImmOp32 = FloatToBits(tmp_float);
3278
3279 if (IsGPR) {
3280 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3281 Out, STI))
3282 return true;
3283 return false;
3284 } else {
3285 unsigned ATReg = getATReg(IDLoc);
3286 if (!ATReg)
3287 return true;
3288 if (LoImmOp64 == 0) {
3289 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3290 Out, STI))
3291 return true;
3292 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3293 return false;
3294 }
3295
3296 MCSection *CS = getStreamer().getCurrentSectionOnly();
3297 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3298 // where appropriate.
3299 MCSection *ReadOnlySection = getContext().getELFSection(
3300 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3301
3302 MCSymbol *Sym = getContext().createTempSymbol();
3303 const MCExpr *LoSym =
3304 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3305 const MipsMCExpr *LoExpr =
3306 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3307
3308 getStreamer().SwitchSection(ReadOnlySection);
3309 getStreamer().EmitLabel(Sym, IDLoc);
3310 getStreamer().EmitIntValue(ImmOp32, 4);
3311 getStreamer().SwitchSection(CS);
3312
3313 if(emitPartialAddress(TOut, IDLoc, Sym))
3314 return true;
3315 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3316 MCOperand::createExpr(LoExpr), IDLoc, STI);
3317 }
3318 return false;
3319 }
3320
3321 // if(!IsSingle)
3322 unsigned ATReg = getATReg(IDLoc);
3323 if (!ATReg)
3324 return true;
3325
3326 if (IsGPR) {
3327 if (LoImmOp64 == 0) {
3328 if(isABI_N32() || isABI_N64()) {
3329 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3330 IDLoc, Out, STI))
3331 return true;
3332 return false;
3333 } else {
3334 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3335 IDLoc, Out, STI))
3336 return true;
3337
3338 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3339 IDLoc, Out, STI))
3340 return true;
3341 return false;
3342 }
3343 }
3344
3345 MCSection *CS = getStreamer().getCurrentSectionOnly();
3346 MCSection *ReadOnlySection = getContext().getELFSection(
3347 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3348
3349 MCSymbol *Sym = getContext().createTempSymbol();
3350 const MCExpr *LoSym =
3351 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3352 const MipsMCExpr *LoExpr =
3353 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3354
3355 getStreamer().SwitchSection(ReadOnlySection);
3356 getStreamer().EmitLabel(Sym, IDLoc);
3357 getStreamer().EmitIntValue(HiImmOp64, 4);
3358 getStreamer().EmitIntValue(LoImmOp64, 4);
3359 getStreamer().SwitchSection(CS);
3360
3361 if(emitPartialAddress(TOut, IDLoc, Sym))
3362 return true;
3363 if(isABI_N64())
3364 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3365 MCOperand::createExpr(LoExpr), IDLoc, STI);
3366 else
3367 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3368 MCOperand::createExpr(LoExpr), IDLoc, STI);
3369
3370 if(isABI_N32() || isABI_N64())
3371 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3372 else {
3373 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3374 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3375 }
3376 return false;
3377 } else { // if(!IsGPR && !IsSingle)
3378 if ((LoImmOp64 == 0) &&
3379 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3380 // FIXME: In the case where the constant is zero, we can load the
3381 // register directly from the zero register.
3382 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3383 Out, STI))
3384 return true;
3385 if (isABI_N32() || isABI_N64())
3386 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3387 else if (hasMips32r2()) {
3388 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3389 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3390 } else {
3391 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3392 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3393 }
3394 return false;
3395 }
3396
3397 MCSection *CS = getStreamer().getCurrentSectionOnly();
3398 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3399 // where appropriate.
3400 MCSection *ReadOnlySection = getContext().getELFSection(
3401 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3402
3403 MCSymbol *Sym = getContext().createTempSymbol();
3404 const MCExpr *LoSym =
3405 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3406 const MipsMCExpr *LoExpr =
3407 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3408
3409 getStreamer().SwitchSection(ReadOnlySection);
3410 getStreamer().EmitLabel(Sym, IDLoc);
3411 getStreamer().EmitIntValue(HiImmOp64, 4);
3412 getStreamer().EmitIntValue(LoImmOp64, 4);
3413 getStreamer().SwitchSection(CS);
3414
3415 if(emitPartialAddress(TOut, IDLoc, Sym))
3416 return true;
3417 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3418 MCOperand::createExpr(LoExpr), IDLoc, STI);
3419 }
3420 return false;
3421}
3422
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003423bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3424 MCStreamer &Out,
3425 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003426 MipsTargetStreamer &TOut = getTargetStreamer();
3427
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003428 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3429 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003430
3431 MCOperand Offset = Inst.getOperand(0);
3432 if (Offset.isExpr()) {
3433 Inst.clear();
3434 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003435 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3436 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3437 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003438 } else {
3439 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003440 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003441 // If offset fits into 11 bits then this instruction becomes microMIPS
3442 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003443 if (inMicroMipsMode())
3444 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003445 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003446 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003447 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003448 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003449 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003450 Inst.clear();
3451 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003452 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3453 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3454 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003455 }
3456 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003457 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003458
Zoran Jovanovicada70912015-09-07 11:56:37 +00003459 // If .set reorder is active and branch instruction has a delay slot,
3460 // emit a NOP after it.
3461 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3462 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003463 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003464
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003465 return false;
3466}
3467
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003468bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3469 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003470 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003471 const MCOperand &DstRegOp = Inst.getOperand(0);
3472 assert(DstRegOp.isReg() && "expected register operand kind");
3473
3474 const MCOperand &ImmOp = Inst.getOperand(1);
3475 assert(ImmOp.isImm() && "expected immediate operand kind");
3476
3477 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003478 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3479 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003480
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003481 bool IsLikely = false;
3482
Toma Tabacue1e460d2015-06-11 10:36:10 +00003483 unsigned OpCode = 0;
3484 switch(Inst.getOpcode()) {
3485 case Mips::BneImm:
3486 OpCode = Mips::BNE;
3487 break;
3488 case Mips::BeqImm:
3489 OpCode = Mips::BEQ;
3490 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003491 case Mips::BEQLImmMacro:
3492 OpCode = Mips::BEQL;
3493 IsLikely = true;
3494 break;
3495 case Mips::BNELImmMacro:
3496 OpCode = Mips::BNEL;
3497 IsLikely = true;
3498 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003499 default:
3500 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3501 break;
3502 }
3503
3504 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003505 if (ImmValue == 0) {
3506 if (IsLikely) {
3507 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3508 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3509 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3510 } else
3511 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3512 STI);
3513 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003514 warnIfNoMacro(IDLoc);
3515
3516 unsigned ATReg = getATReg(IDLoc);
3517 if (!ATReg)
3518 return true;
3519
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003520 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003521 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003522 return true;
3523
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003524 if (IsLikely) {
3525 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3526 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3527 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3528 } else
3529 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003530 }
3531 return false;
3532}
3533
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003534void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Simon Atanasyana1882672018-05-24 07:36:11 +00003535 const MCSubtargetInfo *STI, bool IsLoad) {
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003536 const MCOperand &DstRegOp = Inst.getOperand(0);
3537 assert(DstRegOp.isReg() && "expected register operand kind");
3538 const MCOperand &BaseRegOp = Inst.getOperand(1);
3539 assert(BaseRegOp.isReg() && "expected register operand kind");
3540 const MCOperand &OffsetOp = Inst.getOperand(2);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003541
Simon Atanasyanbe8a42e2018-05-24 07:36:06 +00003542 MipsTargetStreamer &TOut = getTargetStreamer();
3543 unsigned DstReg = DstRegOp.getReg();
3544 unsigned BaseReg = BaseRegOp.getReg();
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003545 unsigned TmpReg = DstReg;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003546
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003547 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003548 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3549 unsigned DstRegClassID =
3550 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3551 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3552 (DstRegClassID == Mips::GPR64RegClassID);
3553
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003554 if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003555 // At this point we need AT to perform the expansions
3556 // and we exit if it is not available.
3557 TmpReg = getATReg(IDLoc);
3558 if (!TmpReg)
3559 return;
3560 }
3561
Simon Atanasyana1882672018-05-24 07:36:11 +00003562 if (OffsetOp.isImm()) {
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003563 int64_t LoOffset = OffsetOp.getImm() & 0xffff;
3564 int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
3565
3566 // If msb of LoOffset is 1(negative number) we must increment
3567 // HiOffset to account for the sign-extension of the low part.
3568 if (LoOffset & 0x8000)
3569 HiOffset += 0x10000;
3570
3571 bool IsLargeOffset = HiOffset != 0;
3572
3573 if (IsLargeOffset) {
3574 bool Is32BitImm = (HiOffset >> 32) == 0;
3575 if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
3576 IDLoc, Out, STI))
3577 return;
3578 }
3579
3580 if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3581 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
3582 BaseReg, IDLoc, STI);
3583 TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
Simon Atanasyanf6b0c932018-05-24 07:36:18 +00003584 } else {
3585 assert(OffsetOp.isExpr() && "expected expression operand kind");
3586 const MCExpr *ExprOffset = OffsetOp.getExpr();
3587 MCOperand LoOperand = MCOperand::createExpr(
3588 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3589 MCOperand HiOperand = MCOperand::createExpr(
3590 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Simon Atanasyane80c3ce2018-06-01 16:37:53 +00003591
3592 if (IsLoad)
3593 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3594 LoOperand, TmpReg, IDLoc, STI);
3595 else
3596 TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3597 LoOperand, TmpReg, IDLoc, STI);
Daniel Sandersfba875f2016-04-29 13:43:45 +00003598 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003599}
3600
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003601bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3602 MCStreamer &Out,
3603 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003604 unsigned OpNum = Inst.getNumOperands();
3605 unsigned Opcode = Inst.getOpcode();
3606 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3607
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003608 assert(Inst.getOperand(OpNum - 1).isImm() &&
3609 Inst.getOperand(OpNum - 2).isReg() &&
3610 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003611
3612 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3613 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003614 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3615 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3616 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3617 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003618 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003619 if (inMicroMipsMode() && hasMips32r6())
3620 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3621 else
3622 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3623 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003624
3625 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003626 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003627 return false;
3628}
3629
Toma Tabacu1a108322015-06-17 13:20:24 +00003630bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003631 MCStreamer &Out,
3632 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003633 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003634 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003635 unsigned PseudoOpcode = Inst.getOpcode();
3636 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003637 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003638 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3639
3640 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003641 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003642
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003643 unsigned TrgReg;
3644 if (TrgOp.isReg())
3645 TrgReg = TrgOp.getReg();
3646 else if (TrgOp.isImm()) {
3647 warnIfNoMacro(IDLoc);
3648 EmittedNoMacroWarning = true;
3649
3650 TrgReg = getATReg(IDLoc);
3651 if (!TrgReg)
3652 return true;
3653
3654 switch(PseudoOpcode) {
3655 default:
3656 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3657 case Mips::BLTImmMacro:
3658 PseudoOpcode = Mips::BLT;
3659 break;
3660 case Mips::BLEImmMacro:
3661 PseudoOpcode = Mips::BLE;
3662 break;
3663 case Mips::BGEImmMacro:
3664 PseudoOpcode = Mips::BGE;
3665 break;
3666 case Mips::BGTImmMacro:
3667 PseudoOpcode = Mips::BGT;
3668 break;
3669 case Mips::BLTUImmMacro:
3670 PseudoOpcode = Mips::BLTU;
3671 break;
3672 case Mips::BLEUImmMacro:
3673 PseudoOpcode = Mips::BLEU;
3674 break;
3675 case Mips::BGEUImmMacro:
3676 PseudoOpcode = Mips::BGEU;
3677 break;
3678 case Mips::BGTUImmMacro:
3679 PseudoOpcode = Mips::BGTU;
3680 break;
3681 case Mips::BLTLImmMacro:
3682 PseudoOpcode = Mips::BLTL;
3683 break;
3684 case Mips::BLELImmMacro:
3685 PseudoOpcode = Mips::BLEL;
3686 break;
3687 case Mips::BGELImmMacro:
3688 PseudoOpcode = Mips::BGEL;
3689 break;
3690 case Mips::BGTLImmMacro:
3691 PseudoOpcode = Mips::BGTL;
3692 break;
3693 case Mips::BLTULImmMacro:
3694 PseudoOpcode = Mips::BLTUL;
3695 break;
3696 case Mips::BLEULImmMacro:
3697 PseudoOpcode = Mips::BLEUL;
3698 break;
3699 case Mips::BGEULImmMacro:
3700 PseudoOpcode = Mips::BGEUL;
3701 break;
3702 case Mips::BGTULImmMacro:
3703 PseudoOpcode = Mips::BGTUL;
3704 break;
3705 }
3706
3707 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003708 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003709 return true;
3710 }
3711
Toma Tabacu1a108322015-06-17 13:20:24 +00003712 switch (PseudoOpcode) {
3713 case Mips::BLT:
3714 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003715 case Mips::BLTL:
3716 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003717 AcceptsEquality = false;
3718 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003719 IsUnsigned =
3720 ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003721 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003722 ZeroSrcOpcode = Mips::BGTZ;
3723 ZeroTrgOpcode = Mips::BLTZ;
3724 break;
3725 case Mips::BLE:
3726 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003727 case Mips::BLEL:
3728 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003729 AcceptsEquality = true;
3730 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003731 IsUnsigned =
3732 ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003733 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003734 ZeroSrcOpcode = Mips::BGEZ;
3735 ZeroTrgOpcode = Mips::BLEZ;
3736 break;
3737 case Mips::BGE:
3738 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003739 case Mips::BGEL:
3740 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003741 AcceptsEquality = true;
3742 ReverseOrderSLT = false;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003743 IsUnsigned =
3744 ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003745 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003746 ZeroSrcOpcode = Mips::BLEZ;
3747 ZeroTrgOpcode = Mips::BGEZ;
3748 break;
3749 case Mips::BGT:
3750 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003751 case Mips::BGTL:
3752 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003753 AcceptsEquality = false;
3754 ReverseOrderSLT = true;
Simon Atanasyan478220f2018-05-24 07:36:00 +00003755 IsUnsigned =
3756 ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003757 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003758 ZeroSrcOpcode = Mips::BLTZ;
3759 ZeroTrgOpcode = Mips::BGTZ;
3760 break;
3761 default:
3762 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3763 }
3764
Toma Tabacu1a108322015-06-17 13:20:24 +00003765 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3766 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3767 if (IsSrcRegZero && IsTrgRegZero) {
3768 // FIXME: All of these Opcode-specific if's are needed for compatibility
3769 // with GAS' behaviour. However, they may not generate the most efficient
3770 // code in some circumstances.
3771 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003772 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3773 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003774 return false;
3775 }
3776 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003777 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3778 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003779 Warning(IDLoc, "branch is always taken");
3780 return false;
3781 }
3782 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003783 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3784 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003785 Warning(IDLoc, "branch is always taken");
3786 return false;
3787 }
3788 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003789 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3790 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003791 return false;
3792 }
3793 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003794 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3795 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003796 return false;
3797 }
3798 if (AcceptsEquality) {
3799 // If both registers are $0 and the pseudo-branch accepts equality, it
3800 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003801 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3802 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003803 Warning(IDLoc, "branch is always taken");
3804 return false;
3805 }
3806 // If both registers are $0 and the pseudo-branch does not accept
3807 // equality, it will never be taken, so we don't have to emit anything.
3808 return false;
3809 }
3810 if (IsSrcRegZero || IsTrgRegZero) {
3811 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3812 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3813 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3814 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3815 // the pseudo-branch will never be taken, so we don't emit anything.
3816 // This only applies to unsigned pseudo-branches.
3817 return false;
3818 }
3819 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3820 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3821 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3822 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3823 // the pseudo-branch will always be taken, so we emit an unconditional
3824 // branch.
3825 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003826 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3827 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003828 Warning(IDLoc, "branch is always taken");
3829 return false;
3830 }
3831 if (IsUnsigned) {
3832 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3833 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3834 // the pseudo-branch will be taken only when the non-zero register is
3835 // different from 0, so we emit a BNEZ.
3836 //
3837 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3838 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3839 // the pseudo-branch will be taken only when the non-zero register is
3840 // equal to 0, so we emit a BEQZ.
3841 //
3842 // Because only BLEU and BGEU branch on equality, we can use the
3843 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003844 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3845 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3846 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003847 return false;
3848 }
3849 // If we have a signed pseudo-branch and one of the registers is $0,
3850 // we can use an appropriate compare-to-zero branch. We select which one
3851 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003852 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3853 IsSrcRegZero ? TrgReg : SrcReg,
3854 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003855 return false;
3856 }
3857
3858 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3859 // expansions. If it is not available, we return.
3860 unsigned ATRegNum = getATReg(IDLoc);
3861 if (!ATRegNum)
3862 return true;
3863
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003864 if (!EmittedNoMacroWarning)
3865 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003866
3867 // SLT fits well with 2 of our 4 pseudo-branches:
3868 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3869 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3870 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3871 // This is accomplished by using a BNEZ with the result of the SLT.
3872 //
3873 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003874 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003875 // Because only BGE and BLE branch on equality, we can use the
3876 // AcceptsEquality variable to decide when to emit the BEQZ.
3877 // Note that the order of the SLT arguments doesn't change between
3878 // opposites.
3879 //
3880 // The same applies to the unsigned variants, except that SLTu is used
3881 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003882 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3883 ReverseOrderSLT ? TrgReg : SrcReg,
3884 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003885
Daniel Sandersa736b372016-04-29 13:33:12 +00003886 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3887 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3888 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3889 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003890 return false;
3891}
3892
Simon Dardis509da1a2017-02-13 16:06:48 +00003893// Expand a integer division macro.
3894//
3895// Notably we don't have to emit a warning when encountering $rt as the $zero
3896// register, or 0 as an immediate. processInstruction() has already done that.
3897//
3898// The destination register can only be $zero when expanding (S)DivIMacro or
3899// D(S)DivMacro.
3900
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003901bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3902 const MCSubtargetInfo *STI, const bool IsMips64,
3903 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003904 MipsTargetStreamer &TOut = getTargetStreamer();
3905
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003906 warnIfNoMacro(IDLoc);
3907
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003908 const MCOperand &RdRegOp = Inst.getOperand(0);
3909 assert(RdRegOp.isReg() && "expected register operand kind");
3910 unsigned RdReg = RdRegOp.getReg();
3911
3912 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003913 assert(RsRegOp.isReg() && "expected register operand kind");
3914 unsigned RsReg = RsRegOp.getReg();
3915
Simon Dardis12850ee2017-01-31 10:49:24 +00003916 unsigned RtReg;
3917 int64_t ImmValue;
3918
3919 const MCOperand &RtOp = Inst.getOperand(2);
3920 assert((RtOp.isReg() || RtOp.isImm()) &&
3921 "expected register or immediate operand kind");
3922 if (RtOp.isReg())
3923 RtReg = RtOp.getReg();
3924 else
3925 ImmValue = RtOp.getImm();
3926
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003927 unsigned DivOp;
3928 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003929 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003930
3931 if (IsMips64) {
3932 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3933 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003934 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003935 } else {
3936 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3937 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003938 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003939 }
3940
3941 bool UseTraps = useTraps();
3942
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003943 unsigned Opcode = Inst.getOpcode();
3944 bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
3945 Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
3946 Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
3947 Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
3948
3949 bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
3950 Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
3951 Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
3952 Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
3953
Simon Dardis12850ee2017-01-31 10:49:24 +00003954 if (RtOp.isImm()) {
3955 unsigned ATReg = getATReg(IDLoc);
3956 if (!ATReg)
3957 return true;
3958
3959 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003960 if (UseTraps)
3961 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3962 else
3963 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3964 return false;
3965 }
3966
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003967 if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
3968 TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
3969 return false;
3970 } else if (isDiv && ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003971 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003972 return false;
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003973 } else if (isDiv && Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003974 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003975 return false;
3976 } else {
3977 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3978 false, Inst.getLoc(), Out, STI))
3979 return true;
3980 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003981 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003982 return false;
3983 }
3984 return true;
3985 }
3986
Stefan Maksimovic0a239982018-07-09 13:06:44 +00003987 // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
3988 // break, insert the trap/break and exit. This gives a different result to
3989 // GAS. GAS has an inconsistency/missed optimization in that not all cases
3990 // are handled equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003991 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003992 if (UseTraps) {
3993 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003994 return false;
3995 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003996 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3997 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003998 }
3999
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004000 // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
4001 // not expand to macro sequence.
4002 if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
4003 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
4004 return false;
4005 }
4006
Simon Dardis509da1a2017-02-13 16:06:48 +00004007 // Temporary label for first branch traget
4008 MCContext &Context = TOut.getStreamer().getContext();
4009 MCSymbol *BrTarget;
4010 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004011
4012 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004013 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004014 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004015 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004016 BrTarget = Context.createTempSymbol();
4017 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4018 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004019 }
4020
Daniel Sandersa736b372016-04-29 13:33:12 +00004021 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004022
4023 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004024 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004025
4026 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004027 if (!UseTraps)
4028 TOut.getStreamer().EmitLabel(BrTarget);
4029
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004030 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004031 return false;
4032 }
4033
4034 unsigned ATReg = getATReg(IDLoc);
4035 if (!ATReg)
4036 return true;
4037
Simon Dardis509da1a2017-02-13 16:06:48 +00004038 if (!UseTraps)
4039 TOut.getStreamer().EmitLabel(BrTarget);
4040
Daniel Sandersa736b372016-04-29 13:33:12 +00004041 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004042
4043 // Temporary label for the second branch target.
4044 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4045 MCOperand LabelOpEnd =
4046 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4047
4048 // Branch to the mflo instruction.
4049 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4050
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004051 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004052 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004053 TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004054 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004055 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004056 }
4057
4058 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004059 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004060 else {
4061 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004062 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004063 TOut.emitNop(IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004064 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004065 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004066
4067 TOut.getStreamer().EmitLabel(BrTargetEnd);
Stefan Maksimovic0a239982018-07-09 13:06:44 +00004068 TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004069 return false;
4070}
4071
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004072bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004073 SMLoc IDLoc, MCStreamer &Out,
4074 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004075 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004076
4077 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4078 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4079 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4080
4081 unsigned FirstReg = Inst.getOperand(0).getReg();
4082 unsigned SecondReg = Inst.getOperand(1).getReg();
4083 unsigned ThirdReg = Inst.getOperand(2).getReg();
4084
4085 if (hasMips1() && !hasMips2()) {
4086 unsigned ATReg = getATReg(IDLoc);
4087 if (!ATReg)
4088 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004089 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4090 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4091 TOut.emitNop(IDLoc, STI);
4092 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4093 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4094 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4095 TOut.emitNop(IDLoc, STI);
4096 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4097 : Mips::CVT_W_S,
4098 FirstReg, SecondReg, IDLoc, STI);
4099 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4100 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004101 return false;
4102 }
4103
Daniel Sandersa736b372016-04-29 13:33:12 +00004104 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4105 : Mips::TRUNC_W_S,
4106 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004107
4108 return false;
4109}
4110
Daniel Sanders6394ee52015-10-15 14:52:58 +00004111bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004112 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004113 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004114 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004115 }
4116
Toma Tabacud88d79c2015-06-23 14:39:42 +00004117 const MCOperand &DstRegOp = Inst.getOperand(0);
4118 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004119 const MCOperand &SrcRegOp = Inst.getOperand(1);
4120 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004121 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4122 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4123
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004124 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004125 unsigned DstReg = DstRegOp.getReg();
4126 unsigned SrcReg = SrcRegOp.getReg();
4127 int64_t OffsetValue = OffsetImmOp.getImm();
4128
4129 // NOTE: We always need AT for ULHU, as it is always used as the source
4130 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004131 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004132 unsigned ATReg = getATReg(IDLoc);
4133 if (!ATReg)
4134 return true;
4135
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004136 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4137 if (IsLargeOffset) {
4138 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4139 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004140 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004141 }
4142
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004143 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4144 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4145 if (isLittle())
4146 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004147
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004148 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4149 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004150
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004151 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4152 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004153
Daniel Sandersa736b372016-04-29 13:33:12 +00004154 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004155 FirstOffset, IDLoc, STI);
4156 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004157 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004158 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004159
4160 return false;
4161}
4162
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004163bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004164 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004165 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004166 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004167 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004168
4169 const MCOperand &DstRegOp = Inst.getOperand(0);
4170 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004171 const MCOperand &SrcRegOp = Inst.getOperand(1);
4172 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004173 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4174 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4175
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004176 MipsTargetStreamer &TOut = getTargetStreamer();
4177 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004178 unsigned SrcReg = SrcRegOp.getReg();
4179 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004180
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004181 warnIfNoMacro(IDLoc);
4182 unsigned ATReg = getATReg(IDLoc);
4183 if (!ATReg)
4184 return true;
4185
4186 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4187 if (IsLargeOffset) {
4188 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4189 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004190 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004191 }
4192
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004193 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4194 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4195 if (isLittle())
4196 std::swap(FirstOffset, SecondOffset);
4197
4198 if (IsLargeOffset) {
4199 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4200 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4201 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4202 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4203 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4204 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004205 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004206 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4207 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4208 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004209 }
4210
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004211 return false;
4212}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004213
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004214bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4215 const MCSubtargetInfo *STI) {
4216 if (hasMips32r6() || hasMips64r6()) {
4217 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4218 }
4219
4220 const MCOperand &DstRegOp = Inst.getOperand(0);
4221 assert(DstRegOp.isReg() && "expected register operand kind");
4222 const MCOperand &SrcRegOp = Inst.getOperand(1);
4223 assert(SrcRegOp.isReg() && "expected register operand kind");
4224 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4225 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4226
4227 MipsTargetStreamer &TOut = getTargetStreamer();
4228 unsigned DstReg = DstRegOp.getReg();
4229 unsigned SrcReg = SrcRegOp.getReg();
4230 int64_t OffsetValue = OffsetImmOp.getImm();
4231
4232 // Compute left/right load/store offsets.
4233 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4234 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4235 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4236 if (isLittle())
4237 std::swap(LxlOffset, LxrOffset);
4238
4239 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4240 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4241 unsigned TmpReg = SrcReg;
4242 if (IsLargeOffset || DoMove) {
4243 warnIfNoMacro(IDLoc);
4244 TmpReg = getATReg(IDLoc);
4245 if (!TmpReg)
4246 return true;
4247 }
4248
4249 if (IsLargeOffset) {
4250 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4251 IDLoc, Out, STI))
4252 return true;
4253 }
4254
4255 if (DoMove)
4256 std::swap(DstReg, TmpReg);
4257
4258 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4259 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4260 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4261 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4262
4263 if (DoMove)
4264 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004265
4266 return false;
4267}
4268
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004269bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004270 MCStreamer &Out,
4271 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004272 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004273
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004274 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4275 assert(Inst.getOperand(0).isReg() &&
4276 Inst.getOperand(1).isReg() &&
4277 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004278
4279 unsigned ATReg = Mips::NoRegister;
4280 unsigned FinalDstReg = Mips::NoRegister;
4281 unsigned DstReg = Inst.getOperand(0).getReg();
4282 unsigned SrcReg = Inst.getOperand(1).getReg();
4283 int64_t ImmValue = Inst.getOperand(2).getImm();
4284
Simon Dardisaa208812017-02-24 14:34:32 +00004285 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004286
4287 unsigned FinalOpcode = Inst.getOpcode();
4288
4289 if (DstReg == SrcReg) {
4290 ATReg = getATReg(Inst.getLoc());
4291 if (!ATReg)
4292 return true;
4293 FinalDstReg = DstReg;
4294 DstReg = ATReg;
4295 }
4296
Simon Atanasyan478220f2018-05-24 07:36:00 +00004297 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
4298 Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004299 switch (FinalOpcode) {
4300 default:
4301 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004302 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004303 FinalOpcode = Mips::ADD;
4304 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004305 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004306 FinalOpcode = Mips::ADDu;
4307 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004308 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004309 FinalOpcode = Mips::AND;
4310 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004311 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004312 FinalOpcode = Mips::NOR;
4313 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004314 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004315 FinalOpcode = Mips::OR;
4316 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004317 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004318 FinalOpcode = Mips::SLT;
4319 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004320 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004321 FinalOpcode = Mips::SLTu;
4322 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004323 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004324 FinalOpcode = Mips::XOR;
4325 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004326 case Mips::ADDi_MM:
4327 FinalOpcode = Mips::ADD_MM;
4328 break;
4329 case Mips::ADDiu_MM:
4330 FinalOpcode = Mips::ADDu_MM;
4331 break;
4332 case Mips::ANDi_MM:
4333 FinalOpcode = Mips::AND_MM;
4334 break;
4335 case Mips::ORi_MM:
4336 FinalOpcode = Mips::OR_MM;
4337 break;
4338 case Mips::SLTi_MM:
4339 FinalOpcode = Mips::SLT_MM;
4340 break;
4341 case Mips::SLTiu_MM:
4342 FinalOpcode = Mips::SLTu_MM;
4343 break;
4344 case Mips::XORi_MM:
4345 FinalOpcode = Mips::XOR_MM;
4346 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004347 case Mips::ANDi64:
4348 FinalOpcode = Mips::AND64;
4349 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004350 case Mips::NORImm64:
4351 FinalOpcode = Mips::NOR64;
4352 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004353 case Mips::ORi64:
4354 FinalOpcode = Mips::OR64;
4355 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004356 case Mips::SLTImm64:
4357 FinalOpcode = Mips::SLT64;
4358 break;
4359 case Mips::SLTUImm64:
4360 FinalOpcode = Mips::SLTu64;
4361 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004362 case Mips::XORi64:
4363 FinalOpcode = Mips::XOR64;
4364 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004365 }
4366
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004367 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004368 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004369 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004370 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004371 return false;
4372 }
4373 return true;
4374}
4375
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004376bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4377 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004378 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004379 unsigned ATReg = Mips::NoRegister;
4380 unsigned DReg = Inst.getOperand(0).getReg();
4381 unsigned SReg = Inst.getOperand(1).getReg();
4382 unsigned TReg = Inst.getOperand(2).getReg();
4383 unsigned TmpReg = DReg;
4384
4385 unsigned FirstShift = Mips::NOP;
4386 unsigned SecondShift = Mips::NOP;
4387
4388 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004389 if (DReg == SReg) {
4390 TmpReg = getATReg(Inst.getLoc());
4391 if (!TmpReg)
4392 return true;
4393 }
4394
4395 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004396 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4397 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004398 return false;
4399 }
4400
4401 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004402 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004403 return false;
4404 }
4405
4406 return true;
4407 }
4408
4409 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004410 switch (Inst.getOpcode()) {
4411 default:
4412 llvm_unreachable("unexpected instruction opcode");
4413 case Mips::ROL:
4414 FirstShift = Mips::SRLV;
4415 SecondShift = Mips::SLLV;
4416 break;
4417 case Mips::ROR:
4418 FirstShift = Mips::SLLV;
4419 SecondShift = Mips::SRLV;
4420 break;
4421 }
4422
4423 ATReg = getATReg(Inst.getLoc());
4424 if (!ATReg)
4425 return true;
4426
Daniel Sandersa736b372016-04-29 13:33:12 +00004427 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4428 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4429 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4430 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004431
4432 return false;
4433 }
4434
4435 return true;
4436}
4437
4438bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004439 MCStreamer &Out,
4440 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004441 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004442 unsigned ATReg = Mips::NoRegister;
4443 unsigned DReg = Inst.getOperand(0).getReg();
4444 unsigned SReg = Inst.getOperand(1).getReg();
4445 int64_t ImmValue = Inst.getOperand(2).getImm();
4446
4447 unsigned FirstShift = Mips::NOP;
4448 unsigned SecondShift = Mips::NOP;
4449
4450 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004451 if (Inst.getOpcode() == Mips::ROLImm) {
4452 uint64_t MaxShift = 32;
4453 uint64_t ShiftValue = ImmValue;
4454 if (ImmValue != 0)
4455 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004456 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004457 return false;
4458 }
4459
4460 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004461 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004462 return false;
4463 }
4464
4465 return true;
4466 }
4467
4468 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004469 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004470 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004471 return false;
4472 }
4473
4474 switch (Inst.getOpcode()) {
4475 default:
4476 llvm_unreachable("unexpected instruction opcode");
4477 case Mips::ROLImm:
4478 FirstShift = Mips::SLL;
4479 SecondShift = Mips::SRL;
4480 break;
4481 case Mips::RORImm:
4482 FirstShift = Mips::SRL;
4483 SecondShift = Mips::SLL;
4484 break;
4485 }
4486
4487 ATReg = getATReg(Inst.getLoc());
4488 if (!ATReg)
4489 return true;
4490
Daniel Sandersa736b372016-04-29 13:33:12 +00004491 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4492 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4493 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004494
4495 return false;
4496 }
4497
4498 return true;
4499}
4500
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004501bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4502 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004503 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004504 unsigned ATReg = Mips::NoRegister;
4505 unsigned DReg = Inst.getOperand(0).getReg();
4506 unsigned SReg = Inst.getOperand(1).getReg();
4507 unsigned TReg = Inst.getOperand(2).getReg();
4508 unsigned TmpReg = DReg;
4509
4510 unsigned FirstShift = Mips::NOP;
4511 unsigned SecondShift = Mips::NOP;
4512
4513 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004514 if (TmpReg == SReg) {
4515 TmpReg = getATReg(Inst.getLoc());
4516 if (!TmpReg)
4517 return true;
4518 }
4519
4520 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004521 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4522 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004523 return false;
4524 }
4525
4526 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004527 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004528 return false;
4529 }
4530
4531 return true;
4532 }
4533
4534 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004535 switch (Inst.getOpcode()) {
4536 default:
4537 llvm_unreachable("unexpected instruction opcode");
4538 case Mips::DROL:
4539 FirstShift = Mips::DSRLV;
4540 SecondShift = Mips::DSLLV;
4541 break;
4542 case Mips::DROR:
4543 FirstShift = Mips::DSLLV;
4544 SecondShift = Mips::DSRLV;
4545 break;
4546 }
4547
4548 ATReg = getATReg(Inst.getLoc());
4549 if (!ATReg)
4550 return true;
4551
Daniel Sandersa736b372016-04-29 13:33:12 +00004552 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4553 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4554 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4555 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004556
4557 return false;
4558 }
4559
4560 return true;
4561}
4562
4563bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004564 MCStreamer &Out,
4565 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004566 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004567 unsigned ATReg = Mips::NoRegister;
4568 unsigned DReg = Inst.getOperand(0).getReg();
4569 unsigned SReg = Inst.getOperand(1).getReg();
4570 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4571
4572 unsigned FirstShift = Mips::NOP;
4573 unsigned SecondShift = Mips::NOP;
4574
4575 MCInst TmpInst;
4576
4577 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004578 unsigned FinalOpcode = Mips::NOP;
4579 if (ImmValue == 0)
4580 FinalOpcode = Mips::DROTR;
4581 else if (ImmValue % 32 == 0)
4582 FinalOpcode = Mips::DROTR32;
4583 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4584 if (Inst.getOpcode() == Mips::DROLImm)
4585 FinalOpcode = Mips::DROTR32;
4586 else
4587 FinalOpcode = Mips::DROTR;
4588 } else if (ImmValue >= 33) {
4589 if (Inst.getOpcode() == Mips::DROLImm)
4590 FinalOpcode = Mips::DROTR;
4591 else
4592 FinalOpcode = Mips::DROTR32;
4593 }
4594
4595 uint64_t ShiftValue = ImmValue % 32;
4596 if (Inst.getOpcode() == Mips::DROLImm)
4597 ShiftValue = (32 - ImmValue % 32) % 32;
4598
Daniel Sandersa736b372016-04-29 13:33:12 +00004599 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004600
4601 return false;
4602 }
4603
4604 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004605 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004606 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004607 return false;
4608 }
4609
4610 switch (Inst.getOpcode()) {
4611 default:
4612 llvm_unreachable("unexpected instruction opcode");
4613 case Mips::DROLImm:
4614 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4615 FirstShift = Mips::DSLL;
4616 SecondShift = Mips::DSRL32;
4617 }
4618 if (ImmValue == 32) {
4619 FirstShift = Mips::DSLL32;
4620 SecondShift = Mips::DSRL32;
4621 }
4622 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4623 FirstShift = Mips::DSLL32;
4624 SecondShift = Mips::DSRL;
4625 }
4626 break;
4627 case Mips::DRORImm:
4628 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4629 FirstShift = Mips::DSRL;
4630 SecondShift = Mips::DSLL32;
4631 }
4632 if (ImmValue == 32) {
4633 FirstShift = Mips::DSRL32;
4634 SecondShift = Mips::DSLL32;
4635 }
4636 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4637 FirstShift = Mips::DSRL32;
4638 SecondShift = Mips::DSLL;
4639 }
4640 break;
4641 }
4642
4643 ATReg = getATReg(Inst.getLoc());
4644 if (!ATReg)
4645 return true;
4646
Daniel Sandersa736b372016-04-29 13:33:12 +00004647 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4648 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4649 Inst.getLoc(), STI);
4650 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004651
4652 return false;
4653 }
4654
4655 return true;
4656}
4657
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004658bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4659 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004660 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004661 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4662 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4663
Daniel Sandersa736b372016-04-29 13:33:12 +00004664 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004665 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004666 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004667 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004668 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4669 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004670
4671 return false;
4672}
4673
Simon Dardis3c82a642017-02-08 16:25:05 +00004674bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4675 const MCSubtargetInfo *STI) {
4676 MipsTargetStreamer &TOut = getTargetStreamer();
4677 unsigned ATReg = Mips::NoRegister;
4678 unsigned DstReg = Inst.getOperand(0).getReg();
4679 unsigned SrcReg = Inst.getOperand(1).getReg();
4680 int32_t ImmValue = Inst.getOperand(2).getImm();
4681
4682 ATReg = getATReg(IDLoc);
4683 if (!ATReg)
4684 return true;
4685
Simon Atanasyan478220f2018-05-24 07:36:00 +00004686 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
4687 STI);
Simon Dardis3c82a642017-02-08 16:25:05 +00004688
4689 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4690 SrcReg, ATReg, IDLoc, STI);
4691
4692 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4693
4694 return false;
4695}
4696
4697bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4698 const MCSubtargetInfo *STI) {
4699 MipsTargetStreamer &TOut = getTargetStreamer();
4700 unsigned ATReg = Mips::NoRegister;
4701 unsigned DstReg = Inst.getOperand(0).getReg();
4702 unsigned SrcReg = Inst.getOperand(1).getReg();
4703 unsigned TmpReg = Inst.getOperand(2).getReg();
4704
4705 ATReg = getATReg(Inst.getLoc());
4706 if (!ATReg)
4707 return true;
4708
4709 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4710 SrcReg, TmpReg, IDLoc, STI);
4711
4712 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4713
4714 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4715 DstReg, DstReg, 0x1F, IDLoc, STI);
4716
4717 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4718
4719 if (useTraps()) {
4720 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4721 } else {
4722 MCContext & Context = TOut.getStreamer().getContext();
4723 MCSymbol * BrTarget = Context.createTempSymbol();
4724 MCOperand LabelOp =
4725 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4726
4727 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4728 if (AssemblerOptions.back()->isReorder())
4729 TOut.emitNop(IDLoc, STI);
4730 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4731
4732 TOut.getStreamer().EmitLabel(BrTarget);
4733 }
4734 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4735
4736 return false;
4737}
4738
4739bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4740 const MCSubtargetInfo *STI) {
4741 MipsTargetStreamer &TOut = getTargetStreamer();
4742 unsigned ATReg = Mips::NoRegister;
4743 unsigned DstReg = Inst.getOperand(0).getReg();
4744 unsigned SrcReg = Inst.getOperand(1).getReg();
4745 unsigned TmpReg = Inst.getOperand(2).getReg();
4746
4747 ATReg = getATReg(IDLoc);
4748 if (!ATReg)
4749 return true;
4750
4751 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4752 SrcReg, TmpReg, IDLoc, STI);
4753
4754 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4755 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4756 if (useTraps()) {
4757 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4758 } else {
4759 MCContext & Context = TOut.getStreamer().getContext();
4760 MCSymbol * BrTarget = Context.createTempSymbol();
4761 MCOperand LabelOp =
4762 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4763
4764 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4765 if (AssemblerOptions.back()->isReorder())
4766 TOut.emitNop(IDLoc, STI);
4767 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4768
4769 TOut.getStreamer().EmitLabel(BrTarget);
4770 }
4771
4772 return false;
4773}
4774
4775bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4776 const MCSubtargetInfo *STI) {
4777 MipsTargetStreamer &TOut = getTargetStreamer();
4778 unsigned DstReg = Inst.getOperand(0).getReg();
4779 unsigned SrcReg = Inst.getOperand(1).getReg();
4780 unsigned TmpReg = Inst.getOperand(2).getReg();
4781
4782 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4783 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4784
4785 return false;
4786}
4787
Simon Dardisaff4d142016-10-18 14:28:00 +00004788// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4789// lw $<reg+1>>, offset+4($reg2)'
4790// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4791// sw $<reg+1>>, offset+4($reg2)'
4792// for O32.
4793bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4794 MCStreamer &Out,
4795 const MCSubtargetInfo *STI,
4796 bool IsLoad) {
4797 if (!isABI_O32())
4798 return true;
4799
4800 warnIfNoMacro(IDLoc);
4801
4802 MipsTargetStreamer &TOut = getTargetStreamer();
4803 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4804 unsigned FirstReg = Inst.getOperand(0).getReg();
4805 unsigned SecondReg = nextReg(FirstReg);
4806 unsigned BaseReg = Inst.getOperand(1).getReg();
4807 if (!SecondReg)
4808 return true;
4809
4810 warnIfRegIndexIsAT(FirstReg, IDLoc);
4811
4812 assert(Inst.getOperand(2).isImm() &&
4813 "Offset for load macro is not immediate!");
4814
4815 MCOperand &FirstOffset = Inst.getOperand(2);
4816 signed NextOffset = FirstOffset.getImm() + 4;
4817 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4818
4819 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4820 return true;
4821
4822 // For loads, clobber the base register with the second load instead of the
4823 // first if the BaseReg == FirstReg.
4824 if (FirstReg != BaseReg || !IsLoad) {
4825 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4826 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4827 } else {
4828 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4829 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4830 }
4831
4832 return false;
4833}
4834
Simon Dardis43115a12016-11-21 20:30:41 +00004835bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4836 const MCSubtargetInfo *STI) {
4837
4838 warnIfNoMacro(IDLoc);
4839 MipsTargetStreamer &TOut = getTargetStreamer();
4840
4841 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4842 Inst.getOperand(2).getReg() != Mips::ZERO) {
4843 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4844 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4845 IDLoc, STI);
4846 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4847 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4848 return false;
4849 }
4850
4851 unsigned Reg = 0;
4852 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4853 Reg = Inst.getOperand(2).getReg();
4854 } else {
4855 Reg = Inst.getOperand(1).getReg();
4856 }
4857 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4858 return false;
4859}
4860
4861bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4862 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004863 warnIfNoMacro(IDLoc);
4864 MipsTargetStreamer &TOut = getTargetStreamer();
4865
4866 unsigned Opc;
4867 int64_t Imm = Inst.getOperand(2).getImm();
4868 unsigned Reg = Inst.getOperand(1).getReg();
4869
4870 if (Imm == 0) {
4871 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4872 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4873 return false;
4874 } else {
4875
4876 if (Reg == Mips::ZERO) {
4877 Warning(IDLoc, "comparison is always false");
4878 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4879 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4880 return false;
4881 }
4882
4883 if (Imm > -0x8000 && Imm < 0) {
4884 Imm = -Imm;
4885 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4886 } else {
4887 Opc = Mips::XORi;
4888 }
4889 }
4890 if (!isUInt<16>(Imm)) {
4891 unsigned ATReg = getATReg(IDLoc);
4892 if (!ATReg)
4893 return true;
4894
4895 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4896 Out, STI))
4897 return true;
4898
4899 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4900 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4901 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4902 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4903 return false;
4904 }
4905
4906 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4907 Imm, IDLoc, STI);
4908 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4909 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4910 return false;
4911}
4912
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004913// Map the DSP accumulator and control register to the corresponding gpr
4914// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4915// do not map the DSP registers contigously to gpr registers.
4916static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4917 switch (Inst.getOpcode()) {
4918 case Mips::MFTLO:
4919 case Mips::MTTLO:
4920 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4921 case Mips::AC0:
4922 return Mips::ZERO;
4923 case Mips::AC1:
4924 return Mips::A0;
4925 case Mips::AC2:
4926 return Mips::T0;
4927 case Mips::AC3:
4928 return Mips::T4;
4929 default:
4930 llvm_unreachable("Unknown register for 'mttr' alias!");
4931 }
4932 case Mips::MFTHI:
4933 case Mips::MTTHI:
4934 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4935 case Mips::AC0:
4936 return Mips::AT;
4937 case Mips::AC1:
4938 return Mips::A1;
4939 case Mips::AC2:
4940 return Mips::T1;
4941 case Mips::AC3:
4942 return Mips::T5;
4943 default:
4944 llvm_unreachable("Unknown register for 'mttr' alias!");
4945 }
4946 case Mips::MFTACX:
4947 case Mips::MTTACX:
4948 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4949 case Mips::AC0:
4950 return Mips::V0;
4951 case Mips::AC1:
4952 return Mips::A2;
4953 case Mips::AC2:
4954 return Mips::T2;
4955 case Mips::AC3:
4956 return Mips::T6;
4957 default:
4958 llvm_unreachable("Unknown register for 'mttr' alias!");
4959 }
4960 case Mips::MFTDSP:
4961 case Mips::MTTDSP:
4962 return Mips::S0;
4963 default:
4964 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4965 }
4966}
4967
4968// Map the floating point register operand to the corresponding register
4969// operand.
4970static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4971 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4972 case Mips::F0: return Mips::ZERO;
4973 case Mips::F1: return Mips::AT;
4974 case Mips::F2: return Mips::V0;
4975 case Mips::F3: return Mips::V1;
4976 case Mips::F4: return Mips::A0;
4977 case Mips::F5: return Mips::A1;
4978 case Mips::F6: return Mips::A2;
4979 case Mips::F7: return Mips::A3;
4980 case Mips::F8: return Mips::T0;
4981 case Mips::F9: return Mips::T1;
4982 case Mips::F10: return Mips::T2;
4983 case Mips::F11: return Mips::T3;
4984 case Mips::F12: return Mips::T4;
4985 case Mips::F13: return Mips::T5;
4986 case Mips::F14: return Mips::T6;
4987 case Mips::F15: return Mips::T7;
4988 case Mips::F16: return Mips::S0;
4989 case Mips::F17: return Mips::S1;
4990 case Mips::F18: return Mips::S2;
4991 case Mips::F19: return Mips::S3;
4992 case Mips::F20: return Mips::S4;
4993 case Mips::F21: return Mips::S5;
4994 case Mips::F22: return Mips::S6;
4995 case Mips::F23: return Mips::S7;
4996 case Mips::F24: return Mips::T8;
4997 case Mips::F25: return Mips::T9;
4998 case Mips::F26: return Mips::K0;
4999 case Mips::F27: return Mips::K1;
5000 case Mips::F28: return Mips::GP;
5001 case Mips::F29: return Mips::SP;
5002 case Mips::F30: return Mips::FP;
5003 case Mips::F31: return Mips::RA;
5004 default: llvm_unreachable("Unknown register for mttc1 alias!");
5005 }
5006}
5007
5008// Map the coprocessor operand the corresponding gpr register operand.
5009static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5010 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5011 case Mips::COP00: return Mips::ZERO;
5012 case Mips::COP01: return Mips::AT;
5013 case Mips::COP02: return Mips::V0;
5014 case Mips::COP03: return Mips::V1;
5015 case Mips::COP04: return Mips::A0;
5016 case Mips::COP05: return Mips::A1;
5017 case Mips::COP06: return Mips::A2;
5018 case Mips::COP07: return Mips::A3;
5019 case Mips::COP08: return Mips::T0;
5020 case Mips::COP09: return Mips::T1;
5021 case Mips::COP010: return Mips::T2;
5022 case Mips::COP011: return Mips::T3;
5023 case Mips::COP012: return Mips::T4;
5024 case Mips::COP013: return Mips::T5;
5025 case Mips::COP014: return Mips::T6;
5026 case Mips::COP015: return Mips::T7;
5027 case Mips::COP016: return Mips::S0;
5028 case Mips::COP017: return Mips::S1;
5029 case Mips::COP018: return Mips::S2;
5030 case Mips::COP019: return Mips::S3;
5031 case Mips::COP020: return Mips::S4;
5032 case Mips::COP021: return Mips::S5;
5033 case Mips::COP022: return Mips::S6;
5034 case Mips::COP023: return Mips::S7;
5035 case Mips::COP024: return Mips::T8;
5036 case Mips::COP025: return Mips::T9;
5037 case Mips::COP026: return Mips::K0;
5038 case Mips::COP027: return Mips::K1;
5039 case Mips::COP028: return Mips::GP;
5040 case Mips::COP029: return Mips::SP;
5041 case Mips::COP030: return Mips::FP;
5042 case Mips::COP031: return Mips::RA;
5043 default: llvm_unreachable("Unknown register for mttc0 alias!");
5044 }
5045}
5046
5047/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5048/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5049bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5050 const MCSubtargetInfo *STI) {
5051 MipsTargetStreamer &TOut = getTargetStreamer();
5052 unsigned rd = 0;
5053 unsigned u = 1;
5054 unsigned sel = 0;
5055 unsigned h = 0;
5056 bool IsMFTR = false;
5057 switch (Inst.getOpcode()) {
5058 case Mips::MFTC0:
5059 IsMFTR = true;
5060 LLVM_FALLTHROUGH;
5061 case Mips::MTTC0:
5062 u = 0;
5063 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5064 sel = Inst.getOperand(2).getImm();
5065 break;
5066 case Mips::MFTGPR:
5067 IsMFTR = true;
5068 LLVM_FALLTHROUGH;
5069 case Mips::MTTGPR:
5070 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5071 break;
5072 case Mips::MFTLO:
5073 case Mips::MFTHI:
5074 case Mips::MFTACX:
5075 case Mips::MFTDSP:
5076 IsMFTR = true;
5077 LLVM_FALLTHROUGH;
5078 case Mips::MTTLO:
5079 case Mips::MTTHI:
5080 case Mips::MTTACX:
5081 case Mips::MTTDSP:
5082 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5083 sel = 1;
5084 break;
5085 case Mips::MFTHC1:
5086 h = 1;
5087 LLVM_FALLTHROUGH;
5088 case Mips::MFTC1:
5089 IsMFTR = true;
5090 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5091 sel = 2;
5092 break;
5093 case Mips::MTTHC1:
5094 h = 1;
5095 LLVM_FALLTHROUGH;
5096 case Mips::MTTC1:
5097 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5098 sel = 2;
5099 break;
5100 case Mips::CFTC1:
5101 IsMFTR = true;
5102 LLVM_FALLTHROUGH;
5103 case Mips::CTTC1:
5104 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5105 sel = 3;
5106 break;
5107 }
5108 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5109 unsigned Op1 =
5110 IsMFTR ? rd
5111 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5112 : Inst.getOperand(0).getReg());
5113
5114 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5115 STI);
5116 return false;
5117}
5118
Daniel Sandersc5537422016-07-27 13:49:44 +00005119unsigned
5120MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5121 const OperandVector &Operands) {
5122 switch (Inst.getOpcode()) {
5123 default:
5124 return Match_Success;
5125 case Mips::DATI:
5126 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005127 if (static_cast<MipsOperand &>(*Operands[1])
5128 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5129 return Match_Success;
5130 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005131 }
5132}
Simon Dardis730fdb72017-01-16 13:55:58 +00005133
Matheus Almeida595fcab2014-06-11 15:05:56 +00005134unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005135 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005136 // As described by the MIPSR6 spec, daui must not use the zero operand for
5137 // its source operand.
5138 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005139 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5140 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5141 return Match_RequiresNoZeroRegister;
5142 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005143 // As described by the Mips32r2 spec, the registers Rd and Rs for
5144 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005145 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005146 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005147 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005148 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005149 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005150 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005151 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5152 return Match_RequiresDifferentSrcAndDst;
5153 return Match_Success;
5154 case Mips::LWP_MM:
Simon Dardisb60833c2016-05-31 17:34:42 +00005155 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5156 return Match_RequiresDifferentSrcAndDst;
5157 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005158 case Mips::SYNC:
5159 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5160 return Match_NonZeroOperandForSync;
5161 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005162 case Mips::MFC0:
5163 case Mips::MTC0:
5164 case Mips::MTC2:
5165 case Mips::MFC2:
5166 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5167 return Match_NonZeroOperandForMTCX;
5168 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005169 // As described the MIPSR6 spec, the compact branches that compare registers
5170 // must:
5171 // a) Not use the zero register.
5172 // b) Not use the same register twice.
5173 // c) rs < rt for bnec, beqc.
5174 // NB: For this case, the encoding will swap the operands as their
5175 // ordering doesn't matter. GAS performs this transformation too.
5176 // Hence, that constraint does not have to be enforced.
5177 //
5178 // The compact branches that branch iff the signed addition of two registers
5179 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5180 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005181 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5182 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5183 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5184 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5185 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5186 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005187 case Mips::BLEZC64:
5188 case Mips::BGEZC64:
5189 case Mips::BGTZC64:
5190 case Mips::BLTZC64:
5191 case Mips::BEQZC64:
5192 case Mips::BNEZC64:
5193 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5194 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005195 return Match_RequiresNoZeroRegister;
5196 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005197 case Mips::BGEC: case Mips::BGEC_MMR6:
5198 case Mips::BLTC: case Mips::BLTC_MMR6:
5199 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5200 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5201 case Mips::BEQC: case Mips::BEQC_MMR6:
5202 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005203 case Mips::BGEC64:
5204 case Mips::BLTC64:
5205 case Mips::BGEUC64:
5206 case Mips::BLTUC64:
5207 case Mips::BEQC64:
5208 case Mips::BNEC64:
5209 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5210 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005211 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005212 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5213 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005214 return Match_RequiresNoZeroRegister;
5215 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5216 return Match_RequiresDifferentOperands;
5217 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005218 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005219 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5220 "Operands must be immediates for dins!");
5221 const signed Pos = Inst.getOperand(2).getImm();
5222 const signed Size = Inst.getOperand(3).getImm();
5223 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5224 return Match_RequiresPosSizeRange0_32;
5225 return Match_Success;
5226 }
5227 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005228 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005229 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5230 "Operands must be immediates for dinsm/dinsu!");
5231 const signed Pos = Inst.getOperand(2).getImm();
5232 const signed Size = Inst.getOperand(3).getImm();
5233 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5234 return Match_RequiresPosSizeRange33_64;
5235 return Match_Success;
5236 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005237 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005238 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5239 "Operands must be immediates for DEXTM!");
5240 const signed Pos = Inst.getOperand(2).getImm();
5241 const signed Size = Inst.getOperand(3).getImm();
5242 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5243 return Match_RequiresPosSizeUImm6;
5244 return Match_Success;
5245 }
5246 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005247 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005248 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5249 "Operands must be immediates for dextm/dextu!");
5250 const signed Pos = Inst.getOperand(2).getImm();
5251 const signed Size = Inst.getOperand(3).getImm();
5252 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5253 return Match_RequiresPosSizeRange33_64;
5254 return Match_Success;
5255 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005256 case Mips::CRC32B: case Mips::CRC32CB:
5257 case Mips::CRC32H: case Mips::CRC32CH:
5258 case Mips::CRC32W: case Mips::CRC32CW:
5259 case Mips::CRC32D: case Mips::CRC32CD:
5260 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5261 return Match_RequiresSameSrcAndDst;
5262 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005263 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005264
5265 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5266 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5267 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5268 return Match_NoFCCRegisterForCurrentISA;
5269
5270 return Match_Success;
5271
Matheus Almeida595fcab2014-06-11 15:05:56 +00005272}
5273
Daniel Sanders52da7af2015-11-06 12:11:03 +00005274static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5275 uint64_t ErrorInfo) {
5276 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5277 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5278 if (ErrorLoc == SMLoc())
5279 return Loc;
5280 return ErrorLoc;
5281 }
5282 return Loc;
5283}
5284
David Blaikie960ea3f2014-06-08 16:18:35 +00005285bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5286 OperandVector &Operands,
5287 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005288 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005289 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005290 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005291 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005292 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005293
5294 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005295 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005296 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005297 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005298 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005299 case Match_MissingFeature:
5300 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5301 return true;
5302 case Match_InvalidOperand: {
5303 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005304 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005305 if (ErrorInfo >= Operands.size())
5306 return Error(IDLoc, "too few operands for instruction");
5307
Daniel Sanders52da7af2015-11-06 12:11:03 +00005308 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005309 if (ErrorLoc == SMLoc())
5310 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005311 }
5312
5313 return Error(ErrorLoc, "invalid operand for instruction");
5314 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005315 case Match_NonZeroOperandForSync:
Simon Atanasyan478220f2018-05-24 07:36:00 +00005316 return Error(IDLoc,
5317 "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005318 case Match_NonZeroOperandForMTCX:
5319 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005320 case Match_MnemonicFail:
5321 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005322 case Match_RequiresDifferentSrcAndDst:
5323 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005324 case Match_RequiresDifferentOperands:
5325 return Error(IDLoc, "registers must be different");
5326 case Match_RequiresNoZeroRegister:
5327 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005328 case Match_RequiresSameSrcAndDst:
5329 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005330 case Match_NoFCCRegisterForCurrentISA:
5331 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5332 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005333 case Match_Immz:
5334 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005335 case Match_UImm1_0:
5336 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5337 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005338 case Match_UImm2_0:
5339 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5340 "expected 2-bit unsigned immediate");
5341 case Match_UImm2_1:
5342 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5343 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005344 case Match_UImm3_0:
5345 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5346 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005347 case Match_UImm4_0:
5348 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5349 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005350 case Match_SImm4_0:
5351 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5352 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005353 case Match_UImm5_0:
5354 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5355 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005356 case Match_SImm5_0:
5357 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5358 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005359 case Match_UImm5_1:
5360 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5361 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005362 case Match_UImm5_32:
5363 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5364 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005365 case Match_UImm5_33:
5366 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5367 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005368 case Match_UImm5_0_Report_UImm6:
5369 // This is used on UImm5 operands that have a corresponding UImm5_32
5370 // operand to avoid confusing the user.
5371 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5372 "expected 6-bit unsigned immediate");
5373 case Match_UImm5_Lsl2:
5374 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5375 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005376 case Match_UImmRange2_64:
5377 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5378 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005379 case Match_UImm6_0:
5380 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5381 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005382 case Match_UImm6_Lsl2:
5383 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5384 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005385 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005386 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5387 "expected 6-bit signed immediate");
5388 case Match_UImm7_0:
5389 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5390 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005391 case Match_UImm7_N1:
5392 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5393 "expected immediate in range -1 .. 126");
5394 case Match_SImm7_Lsl2:
5395 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5396 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005397 case Match_UImm8_0:
5398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5399 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005400 case Match_UImm10_0:
5401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5402 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005403 case Match_SImm10_0:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005406 case Match_SImm11_0:
5407 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5408 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005409 case Match_UImm16:
5410 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005411 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005412 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5413 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005414 case Match_SImm16:
5415 case Match_SImm16_Relaxed:
5416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5417 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005418 case Match_SImm19_Lsl2:
5419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5420 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005421 case Match_UImm20_0:
5422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5423 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005424 case Match_UImm26_0:
5425 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5426 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005427 case Match_SImm32:
5428 case Match_SImm32_Relaxed:
5429 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5430 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005431 case Match_UImm32_Coerced:
5432 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5433 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005434 case Match_MemSImm9:
5435 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5436 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005437 case Match_MemSImm10:
5438 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5439 "expected memory with 10-bit signed offset");
5440 case Match_MemSImm10Lsl1:
5441 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5442 "expected memory with 11-bit signed offset and multiple of 2");
5443 case Match_MemSImm10Lsl2:
5444 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5445 "expected memory with 12-bit signed offset and multiple of 4");
5446 case Match_MemSImm10Lsl3:
5447 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5448 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005449 case Match_MemSImm11:
5450 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5451 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005452 case Match_MemSImm12:
5453 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5454 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005455 case Match_MemSImm16:
5456 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5457 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005458 case Match_MemSImmPtr:
5459 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5460 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005461 case Match_RequiresPosSizeRange0_32: {
5462 SMLoc ErrorStart = Operands[3]->getStartLoc();
5463 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5464 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5465 SMRange(ErrorStart, ErrorEnd));
5466 }
Simon Dardis55e44672017-09-14 17:27:53 +00005467 case Match_RequiresPosSizeUImm6: {
5468 SMLoc ErrorStart = Operands[3]->getStartLoc();
5469 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5470 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5471 SMRange(ErrorStart, ErrorEnd));
5472 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005473 case Match_RequiresPosSizeRange33_64: {
5474 SMLoc ErrorStart = Operands[3]->getStartLoc();
5475 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5476 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5477 SMRange(ErrorStart, ErrorEnd));
5478 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005479 }
Craig Topper589ceee2015-01-03 08:16:34 +00005480
5481 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005482}
5483
Toma Tabacud9d344b2015-04-27 14:05:04 +00005484void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5485 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5486 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5487 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005488}
5489
Toma Tabacu81496c12015-05-20 08:54:45 +00005490void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5491 if (!AssemblerOptions.back()->isMacro())
5492 Warning(Loc, "macro instruction expanded into multiple instructions");
5493}
5494
Simon Dardis6a319922018-05-25 16:15:48 +00005495void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
5496 const OperandVector &Operands) {
5497 assert(
5498 (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
5499 "Unexpected instruction!");
5500 ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
5501 int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
5502 Inst.addOperand(MCOperand::createReg(NextReg));
5503 ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
5504}
5505
Daniel Sandersef638fe2014-10-03 15:37:37 +00005506void
5507MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5508 SMRange Range, bool ShowColors) {
5509 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005510 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005511 ShowColors);
5512}
5513
Jack Carter1ac53222013-02-20 23:11:17 +00005514int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005515 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005516
Vladimir Medic4c299852013-11-06 11:27:05 +00005517 CC = StringSwitch<unsigned>(Name)
5518 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005519 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005520 .Case("a0", 4)
5521 .Case("a1", 5)
5522 .Case("a2", 6)
5523 .Case("a3", 7)
5524 .Case("v0", 2)
5525 .Case("v1", 3)
5526 .Case("s0", 16)
5527 .Case("s1", 17)
5528 .Case("s2", 18)
5529 .Case("s3", 19)
5530 .Case("s4", 20)
5531 .Case("s5", 21)
5532 .Case("s6", 22)
5533 .Case("s7", 23)
5534 .Case("k0", 26)
5535 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005536 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005537 .Case("sp", 29)
5538 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005539 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005540 .Case("ra", 31)
5541 .Case("t0", 8)
5542 .Case("t1", 9)
5543 .Case("t2", 10)
5544 .Case("t3", 11)
5545 .Case("t4", 12)
5546 .Case("t5", 13)
5547 .Case("t6", 14)
5548 .Case("t7", 15)
5549 .Case("t8", 24)
5550 .Case("t9", 25)
5551 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005552
Toma Tabacufda445c2014-09-15 15:33:01 +00005553 if (!(isABI_N32() || isABI_N64()))
5554 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005555
Daniel Sandersef638fe2014-10-03 15:37:37 +00005556 if (12 <= CC && CC <= 15) {
5557 // Name is one of t4-t7
5558 AsmToken RegTok = getLexer().peekTok();
5559 SMRange RegRange = RegTok.getLocRange();
5560
5561 StringRef FixedName = StringSwitch<StringRef>(Name)
5562 .Case("t4", "t0")
5563 .Case("t5", "t1")
5564 .Case("t6", "t2")
5565 .Case("t7", "t3")
5566 .Default("");
5567 assert(FixedName != "" && "Register name is not one of t4-t7.");
5568
5569 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5570 "Did you mean $" + FixedName + "?", RegRange);
5571 }
5572
Toma Tabacufda445c2014-09-15 15:33:01 +00005573 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5574 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5575 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5576 if (8 <= CC && CC <= 11)
5577 CC += 4;
5578
5579 if (CC == -1)
5580 CC = StringSwitch<unsigned>(Name)
5581 .Case("a4", 8)
5582 .Case("a5", 9)
5583 .Case("a6", 10)
5584 .Case("a7", 11)
5585 .Case("kt0", 26)
5586 .Case("kt1", 27)
5587 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005588
5589 return CC;
5590}
Jack Carterd0bd6422013-04-18 00:41:53 +00005591
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005592int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5593 int CC;
5594
5595 CC = StringSwitch<unsigned>(Name)
5596 .Case("hwr_cpunum", 0)
5597 .Case("hwr_synci_step", 1)
5598 .Case("hwr_cc", 2)
5599 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005600 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005601 .Default(-1);
5602
5603 return CC;
5604}
5605
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005606int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005607 if (Name[0] == 'f') {
5608 StringRef NumString = Name.substr(1);
5609 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005610 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005611 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005612 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005613 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005614 return IntVal;
5615 }
5616 return -1;
5617}
Jack Cartera63b16a2012-09-07 00:23:42 +00005618
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005619int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005620 if (Name.startswith("fcc")) {
5621 StringRef NumString = Name.substr(3);
5622 unsigned IntVal;
5623 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005624 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005625 if (IntVal > 7) // There are only 8 fcc registers.
5626 return -1;
5627 return IntVal;
5628 }
5629 return -1;
5630}
5631
5632int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005633 if (Name.startswith("ac")) {
5634 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005635 unsigned IntVal;
5636 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005637 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005638 if (IntVal > 3) // There are only 3 acc registers.
5639 return -1;
5640 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005641 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005642 return -1;
5643}
Jack Carterd0bd6422013-04-18 00:41:53 +00005644
Jack Carter5dc8ac92013-09-25 23:50:44 +00005645int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5646 unsigned IntVal;
5647
5648 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5649 return -1;
5650
5651 if (IntVal > 31)
5652 return -1;
5653
5654 return IntVal;
5655}
5656
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005657int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5658 int CC;
5659
5660 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005661 .Case("msair", 0)
5662 .Case("msacsr", 1)
5663 .Case("msaaccess", 2)
5664 .Case("msasave", 3)
5665 .Case("msamodify", 4)
5666 .Case("msarequest", 5)
5667 .Case("msamap", 6)
5668 .Case("msaunmap", 7)
5669 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005670
5671 return CC;
5672}
5673
Simon Dardis3aa8a902017-02-06 12:43:46 +00005674bool MipsAsmParser::canUseATReg() {
5675 return AssemblerOptions.back()->getATRegIndex() != 0;
5676}
5677
Toma Tabacu89a712b2015-04-15 10:48:56 +00005678unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005679 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005680 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005681 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005682 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005683 return 0;
5684 }
5685 unsigned AT = getReg(
5686 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005687 return AT;
5688}
Jack Carter0b744b32012-10-04 02:29:46 +00005689
Jack Carterd0bd6422013-04-18 00:41:53 +00005690unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005691 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005692}
5693
Toma Tabacu13964452014-09-04 13:23:44 +00005694bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005695 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005696 LLVM_DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005697
Jack Carter30a59822012-10-04 04:03:53 +00005698 // Check if the current operand has a custom associated parser, if so, try to
5699 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005700 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5701 if (ResTy == MatchOperand_Success)
5702 return false;
5703 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5704 // there was a match, but an error occurred, in which case, just return that
5705 // the operand parsing failed.
5706 if (ResTy == MatchOperand_ParseFail)
5707 return true;
5708
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005709 LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005710
Jack Carterb4dbc172012-09-05 23:34:03 +00005711 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005712 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005713 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005714 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005715
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005716 // Almost all registers have been parsed by custom parsers. There is only
5717 // one exception to this. $zero (and it's alias $0) will reach this point
5718 // for div, divu, and similar instructions because it is not an operand
5719 // to the instruction definition but an explicit register. Special case
5720 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005721 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005722 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005723
Jack Carterd0bd6422013-04-18 00:41:53 +00005724 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005725 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005726 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005727 return true;
5728
Jack Carter873c7242013-01-12 01:03:14 +00005729 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005730 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005731 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005732 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005733 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005734
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005735 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005736 return false;
5737 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005738 default: {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005739 LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005740
5741 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005742 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005743 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005744 return true;
5745
Jack Carter873c7242013-01-12 01:03:14 +00005746 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5747
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005748 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005749 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005750 }
Jack Carter0b744b32012-10-04 02:29:46 +00005751 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005752 return true;
5753}
5754
Jack Carterb5cf5902013-04-17 00:18:04 +00005755bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005756 switch (Expr->getKind()) {
5757 case MCExpr::Constant:
5758 return true;
5759 case MCExpr::SymbolRef:
5760 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005761 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005762 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005763 if (!isEvaluated(BE->getLHS()))
5764 return false;
5765 return isEvaluated(BE->getRHS());
5766 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005767 case MCExpr::Unary:
5768 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005769 case MCExpr::Target:
5770 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005771 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005772 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005773}
Jack Carterd0bd6422013-04-18 00:41:53 +00005774
Jack Carterb4dbc172012-09-05 23:34:03 +00005775bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5776 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005777 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005778 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005779 if (ResTy == MatchOperand_Success) {
5780 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005781 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005782 StartLoc = Operand.getStartLoc();
5783 EndLoc = Operand.getEndLoc();
5784
5785 // AFAIK, we only support numeric registers and named GPR's in CFI
5786 // directives.
5787 // Don't worry about eating tokens before failing. Using an unrecognised
5788 // register is a parse error.
5789 if (Operand.isGPRAsmReg()) {
5790 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005791 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005792 }
5793
5794 return (RegNo == (unsigned)-1);
5795 }
5796
5797 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005798 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005799}
5800
Jack Carterb5cf5902013-04-17 00:18:04 +00005801bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005802 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005803
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005804 if (isParenExpr)
5805 return getParser().parseParenExprOfDepth(0, Res, S);
5806 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005807}
5808
Alex Bradbury58eba092016-11-01 16:32:05 +00005809OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005810MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005811 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00005812 LLVM_DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005813 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005814 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005815 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005816 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005817 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005818 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005819
Jack Carterb5cf5902013-04-17 00:18:04 +00005820 if (getLexer().getKind() == AsmToken::LParen) {
5821 Parser.Lex();
5822 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005823 }
5824
Jack Carterb5cf5902013-04-17 00:18:04 +00005825 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005826 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005827 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005828
Jack Carterd0bd6422013-04-18 00:41:53 +00005829 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005830 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005831 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005832 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005833 SMLoc E =
5834 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005835 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005836 return MatchOperand_Success;
5837 }
5838 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005839 SMLoc E =
5840 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005841
Jack Carterd0bd6422013-04-18 00:41:53 +00005842 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005843 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005844 auto Base = MipsOperand::createGPRReg(
5845 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005846 Operands.push_back(
5847 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005848 return MatchOperand_Success;
5849 }
Simon Dardis858915f2016-10-18 15:17:17 +00005850 MCBinaryExpr::Opcode Opcode;
5851 // GAS and LLVM treat comparison operators different. GAS will generate -1
5852 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5853 // highly unlikely to be found in a memory offset expression, we don't
5854 // handle them.
5855 switch (Tok.getKind()) {
5856 case AsmToken::Plus:
5857 Opcode = MCBinaryExpr::Add;
5858 Parser.Lex();
5859 break;
5860 case AsmToken::Minus:
5861 Opcode = MCBinaryExpr::Sub;
5862 Parser.Lex();
5863 break;
5864 case AsmToken::Star:
5865 Opcode = MCBinaryExpr::Mul;
5866 Parser.Lex();
5867 break;
5868 case AsmToken::Pipe:
5869 Opcode = MCBinaryExpr::Or;
5870 Parser.Lex();
5871 break;
5872 case AsmToken::Amp:
5873 Opcode = MCBinaryExpr::And;
5874 Parser.Lex();
5875 break;
5876 case AsmToken::LessLess:
5877 Opcode = MCBinaryExpr::Shl;
5878 Parser.Lex();
5879 break;
5880 case AsmToken::GreaterGreater:
5881 Opcode = MCBinaryExpr::LShr;
5882 Parser.Lex();
5883 break;
5884 case AsmToken::Caret:
5885 Opcode = MCBinaryExpr::Xor;
5886 Parser.Lex();
5887 break;
5888 case AsmToken::Slash:
5889 Opcode = MCBinaryExpr::Div;
5890 Parser.Lex();
5891 break;
5892 case AsmToken::Percent:
5893 Opcode = MCBinaryExpr::Mod;
5894 Parser.Lex();
5895 break;
5896 default:
5897 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5898 return MatchOperand_ParseFail;
5899 }
5900 const MCExpr * NextExpr;
5901 if (getParser().parseExpression(NextExpr))
5902 return MatchOperand_ParseFail;
5903 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005904 }
5905
Jack Carterd0bd6422013-04-18 00:41:53 +00005906 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005907 }
5908
Toma Tabacu13964452014-09-04 13:23:44 +00005909 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005910 if (Res != MatchOperand_Success)
5911 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005912
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005913 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005914 Error(Parser.getTok().getLoc(), "')' expected");
5915 return MatchOperand_ParseFail;
5916 }
5917
Jack Carter873c7242013-01-12 01:03:14 +00005918 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5919
Jack Carterd0bd6422013-04-18 00:41:53 +00005920 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005921
Craig Topper062a2ba2014-04-25 05:30:21 +00005922 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005923 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005924
Jack Carterd0bd6422013-04-18 00:41:53 +00005925 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005926 std::unique_ptr<MipsOperand> op(
5927 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005928 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005929 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005930 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005931 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005932 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5933 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005934 if (IdVal->evaluateAsAbsolute(Imm))
5935 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005936 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005937 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005938 getContext());
5939 }
5940
David Blaikie960ea3f2014-06-08 16:18:35 +00005941 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005942 return MatchOperand_Success;
5943}
5944
David Blaikie960ea3f2014-06-08 16:18:35 +00005945bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005946 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005947 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005948 if (!Sym)
5949 return false;
5950
5951 SMLoc S = Parser.getTok().getLoc();
5952 if (Sym->isVariable()) {
5953 const MCExpr *Expr = Sym->getVariableValue();
Jack Carterd76b2372013-03-21 21:44:16 +00005954 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005955 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005956 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005957 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005958 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005959 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005960 if (ResTy == MatchOperand_Success) {
5961 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005962 return true;
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005963 }
5964 if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005965 llvm_unreachable("Should never ParseFail");
Jack Carterd76b2372013-03-21 21:44:16 +00005966 }
Jack Carterd76b2372013-03-21 21:44:16 +00005967 }
Simon Atanasyan69301c92018-05-29 15:58:06 +00005968 } else if (Sym->isUnset()) {
5969 // If symbol is unset, it might be created in the `parseSetAssignment`
5970 // routine as an alias for a numeric register name.
5971 // Lookup in the aliases list.
5972 auto Entry = RegisterSets.find(Sym->getName());
5973 if (Entry != RegisterSets.end()) {
5974 OperandMatchResultTy ResTy =
5975 matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
5976 if (ResTy == MatchOperand_Success) {
5977 Parser.Lex();
5978 return true;
5979 }
5980 }
Jack Carterd76b2372013-03-21 21:44:16 +00005981 }
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00005982
Jack Carterd76b2372013-03-21 21:44:16 +00005983 return false;
5984}
Jack Carterd0bd6422013-04-18 00:41:53 +00005985
Alex Bradbury58eba092016-11-01 16:32:05 +00005986OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005987MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005988 StringRef Identifier,
5989 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005990 int Index = matchCPURegisterName(Identifier);
5991 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005992 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005993 Index, Identifier, getContext().getRegisterInfo(), S,
5994 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005995 return MatchOperand_Success;
5996 }
5997
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005998 Index = matchHWRegsRegisterName(Identifier);
5999 if (Index != -1) {
6000 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006001 Index, Identifier, getContext().getRegisterInfo(), S,
6002 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00006003 return MatchOperand_Success;
6004 }
6005
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006006 Index = matchFPURegisterName(Identifier);
6007 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006008 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006009 Index, Identifier, getContext().getRegisterInfo(), S,
6010 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006011 return MatchOperand_Success;
6012 }
6013
6014 Index = matchFCCRegisterName(Identifier);
6015 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006016 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006017 Index, Identifier, getContext().getRegisterInfo(), S,
6018 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006019 return MatchOperand_Success;
6020 }
6021
6022 Index = matchACRegisterName(Identifier);
6023 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006024 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006025 Index, Identifier, getContext().getRegisterInfo(), S,
6026 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006027 return MatchOperand_Success;
6028 }
6029
6030 Index = matchMSA128RegisterName(Identifier);
6031 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006032 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006033 Index, Identifier, getContext().getRegisterInfo(), S,
6034 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006035 return MatchOperand_Success;
6036 }
6037
6038 Index = matchMSA128CtrlRegisterName(Identifier);
6039 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006040 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006041 Index, Identifier, getContext().getRegisterInfo(), S,
6042 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006043 return MatchOperand_Success;
6044 }
6045
6046 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006047}
6048
Alex Bradbury58eba092016-11-01 16:32:05 +00006049OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006050MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
6051 const AsmToken &Token, SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006052 if (Token.is(AsmToken::Identifier)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006053 LLVM_DEBUG(dbgs() << ".. identifier\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006054 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006055 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006056 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006057 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006058 } else if (Token.is(AsmToken::Integer)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006059 LLVM_DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006060 int64_t RegNum = Token.getIntVal();
6061 if (RegNum < 0 || RegNum > 31) {
6062 // Show the error, but treat invalid register
6063 // number as a normal one to continue parsing
6064 // and catch other possible errors.
6065 Error(getLexer().getLoc(), "invalid register number");
6066 }
Toma Tabacu13964452014-09-04 13:23:44 +00006067 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006068 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006069 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006070 return MatchOperand_Success;
6071 }
6072
Simon Atanasyanb2d61fa2018-05-29 09:51:33 +00006073 LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006074
6075 return MatchOperand_NoMatch;
6076}
6077
Alex Bradbury58eba092016-11-01 16:32:05 +00006078OperandMatchResultTy
Simon Atanasyan69301c92018-05-29 15:58:06 +00006079MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
6080 auto Token = getLexer().peekTok(false);
6081 return matchAnyRegisterWithoutDollar(Operands, Token, S);
6082}
6083
6084OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006085MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006086 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006087 LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006088
6089 auto Token = Parser.getTok();
6090
6091 SMLoc S = Token.getLoc();
6092
6093 if (Token.isNot(AsmToken::Dollar)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006094 LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006095 if (Token.is(AsmToken::Identifier)) {
6096 if (searchSymbolAlias(Operands))
6097 return MatchOperand_Success;
6098 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006099 LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006100 return MatchOperand_NoMatch;
6101 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006102 LLVM_DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006103
Toma Tabacu13964452014-09-04 13:23:44 +00006104 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006105 if (ResTy == MatchOperand_Success) {
6106 Parser.Lex(); // $
6107 Parser.Lex(); // identifier
6108 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006109 return ResTy;
6110}
6111
Alex Bradbury58eba092016-11-01 16:32:05 +00006112OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006113MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006114 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006115 LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006116
6117 SMLoc S = getLexer().getLoc();
6118
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006119 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006120 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006121 if (ResTy != MatchOperand_NoMatch)
6122 return ResTy;
6123
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006124 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006125 const MCExpr *Expr = nullptr;
6126 if (Parser.parseExpression(Expr)) {
6127 // We have no way of knowing if a symbol was consumed so we must ParseFail
6128 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006129 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006130 Operands.push_back(
6131 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006132 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006133}
6134
Alex Bradbury58eba092016-11-01 16:32:05 +00006135OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006136MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006137 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006138 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006139 // If the first token is '$' we may have register operand. We have to reject
6140 // cases where it is not a register. Complicating the matter is that
6141 // register names are not reserved across all ABIs.
6142 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006143 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006144 if (Parser.getTok().is(AsmToken::Dollar)) {
6145 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6146 ? MatchOperand_ParseFail
6147 : MatchOperand_NoMatch;
6148 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006149 if (getParser().parseExpression(IdVal))
6150 return MatchOperand_ParseFail;
6151 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006152 if (!MCE)
6153 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006154 int64_t Val = MCE->getValue();
6155 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6156 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006157 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006158 return MatchOperand_Success;
6159}
6160
Alex Bradbury58eba092016-11-01 16:32:05 +00006161OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006162MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6163 MCAsmParser &Parser = getParser();
6164 SmallVector<unsigned, 10> Regs;
6165 unsigned RegNo;
6166 unsigned PrevReg = Mips::NoRegister;
6167 bool RegRange = false;
6168 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6169
6170 if (Parser.getTok().isNot(AsmToken::Dollar))
6171 return MatchOperand_ParseFail;
6172
6173 SMLoc S = Parser.getTok().getLoc();
6174 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6175 SMLoc E = getLexer().getLoc();
6176 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6177 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6178 if (RegRange) {
6179 // Remove last register operand because registers from register range
6180 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006181 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6182 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006183 Regs.push_back(RegNo);
6184 } else {
6185 unsigned TmpReg = PrevReg + 1;
6186 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006187 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6188 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6189 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006190 Error(E, "invalid register operand");
6191 return MatchOperand_ParseFail;
6192 }
6193
6194 PrevReg = TmpReg;
6195 Regs.push_back(TmpReg++);
6196 }
6197 }
6198
6199 RegRange = false;
6200 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006201 if ((PrevReg == Mips::NoRegister) &&
6202 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6203 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006204 Error(E, "$16 or $31 expected");
6205 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006206 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6207 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6208 !isGP64bit()) ||
6209 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6210 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6211 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006212 Error(E, "invalid register operand");
6213 return MatchOperand_ParseFail;
6214 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006215 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6216 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6217 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006218 Error(E, "consecutive register numbers expected");
6219 return MatchOperand_ParseFail;
6220 }
6221
6222 Regs.push_back(RegNo);
6223 }
6224
6225 if (Parser.getTok().is(AsmToken::Minus))
6226 RegRange = true;
6227
6228 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6229 !Parser.getTok().isNot(AsmToken::Comma)) {
6230 Error(E, "',' or '-' expected");
6231 return MatchOperand_ParseFail;
6232 }
6233
6234 Lex(); // Consume comma or minus
6235 if (Parser.getTok().isNot(AsmToken::Dollar))
6236 break;
6237
6238 PrevReg = RegNo;
6239 }
6240
6241 SMLoc E = Parser.getTok().getLoc();
6242 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6243 parseMemOperand(Operands);
6244 return MatchOperand_Success;
6245}
6246
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006247/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6248/// either this.
6249/// ::= '(', register, ')'
6250/// handle it before we iterate so we don't get tripped up by the lack of
6251/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006252bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006253 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006254 if (getLexer().is(AsmToken::LParen)) {
6255 Operands.push_back(
6256 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6257 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006258 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006259 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006260 return Error(Loc, "unexpected token in argument list");
6261 }
6262 if (Parser.getTok().isNot(AsmToken::RParen)) {
6263 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006264 return Error(Loc, "unexpected token, expected ')'");
6265 }
6266 Operands.push_back(
6267 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6268 Parser.Lex();
6269 }
6270 return false;
6271}
6272
6273/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6274/// either one of these.
6275/// ::= '[', register, ']'
6276/// ::= '[', integer, ']'
6277/// handle it before we iterate so we don't get tripped up by the lack of
6278/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006279bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006280 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006281 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006282 if (getLexer().is(AsmToken::LBrac)) {
6283 Operands.push_back(
6284 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6285 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006286 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006287 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006288 return Error(Loc, "unexpected token in argument list");
6289 }
6290 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6291 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006292 return Error(Loc, "unexpected token, expected ']'");
6293 }
6294 Operands.push_back(
6295 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6296 Parser.Lex();
6297 }
6298 return false;
6299}
6300
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006301static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS,
6302 unsigned VariantID = 0);
6303
David Blaikie960ea3f2014-06-08 16:18:35 +00006304bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6305 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006306 MCAsmParser &Parser = getParser();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00006307 LLVM_DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006308
6309 // We have reached first instruction, module directive are now forbidden.
6310 getTargetStreamer().forbidModuleDirective();
6311
Vladimir Medic74593e62013-07-17 15:00:42 +00006312 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006313 if (!mnemonicIsValid(Name, 0)) {
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00006314 uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
6315 std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
6316 return Error(NameLoc, "unknown instruction" + Suggestion);
Vladimir Medic74593e62013-07-17 15:00:42 +00006317 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006318 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006319 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006320
6321 // Read the remaining operands.
6322 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6323 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006324 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006325 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006326 return Error(Loc, "unexpected token in argument list");
6327 }
Toma Tabacu13964452014-09-04 13:23:44 +00006328 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006329 return true;
6330 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006331
Jack Carterd0bd6422013-04-18 00:41:53 +00006332 while (getLexer().is(AsmToken::Comma)) {
6333 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006334 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006335 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006336 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006337 return Error(Loc, "unexpected token in argument list");
6338 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006339 // Parse bracket and parenthesis suffixes before we iterate
6340 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006341 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006342 return true;
6343 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006344 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006345 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006346 }
6347 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006348 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6349 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006350 return Error(Loc, "unexpected token in argument list");
6351 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006352 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006353 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006354}
6355
Nirav Dave996fc132016-05-05 14:15:46 +00006356// FIXME: Given that these have the same name, these should both be
6357// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006358bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006359 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006360 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006361}
6362
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006363bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006364 return Error(Loc, ErrorMsg);
6365}
6366
Jack Carter0b744b32012-10-04 02:29:46 +00006367bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006368 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006369 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006370
6371 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006372 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006373
6374 Parser.Lex(); // Eat "noat".
6375
Jack Carterd0bd6422013-04-18 00:41:53 +00006376 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006377 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006378 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006379 return false;
6380 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006381
6382 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006383 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006384 return false;
6385}
Jack Carterd0bd6422013-04-18 00:41:53 +00006386
Jack Carter0b744b32012-10-04 02:29:46 +00006387bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006388 // Line can be: ".set at", which sets $at to $1
6389 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006390 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006391 Parser.Lex(); // Eat "at".
6392
Jack Carter0b744b32012-10-04 02:29:46 +00006393 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006394 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006395 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006396
6397 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006398 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006399 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006400 }
6401
6402 if (getLexer().isNot(AsmToken::Equal)) {
6403 reportParseError("unexpected token, expected equals sign");
6404 return false;
6405 }
6406 Parser.Lex(); // Eat "=".
6407
6408 if (getLexer().isNot(AsmToken::Dollar)) {
6409 if (getLexer().is(AsmToken::EndOfStatement)) {
6410 reportParseError("no register specified");
6411 return false;
6412 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006413 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006414 return false;
6415 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006416 }
6417 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006418
Toma Tabacu16a74492015-02-13 10:30:57 +00006419 // Find out what "reg" is.
6420 unsigned AtRegNo;
6421 const AsmToken &Reg = Parser.getTok();
6422 if (Reg.is(AsmToken::Identifier)) {
6423 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6424 } else if (Reg.is(AsmToken::Integer)) {
6425 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006426 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006427 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006428 return false;
6429 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006430
6431 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006432 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006433 reportParseError("invalid register");
6434 return false;
6435 }
6436 Parser.Lex(); // Eat "reg".
6437
6438 // If this is not the end of the statement, report an error.
6439 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6440 reportParseError("unexpected token, expected end of statement");
6441 return false;
6442 }
6443
6444 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6445
6446 Parser.Lex(); // Consume the EndOfStatement.
6447 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006448}
6449
6450bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006451 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006452 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006453 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006454 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006455 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006456 return false;
6457 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006458 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006459 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006460 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006461 return false;
6462}
6463
6464bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006465 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006466 Parser.Lex();
6467 // If this is not the end of the statement, report an error.
6468 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006469 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006470 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006471 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006472 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006473 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006474 Parser.Lex(); // Consume the EndOfStatement.
6475 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006476}
6477
6478bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006479 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006480 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006481 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006482 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006483 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006484 return false;
6485 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006486 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006487 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006488 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006489 return false;
6490}
6491
6492bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006493 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006494 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006495 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006496 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006497 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006498 return false;
6499 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006500 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006501 reportParseError("`noreorder' must be set before `nomacro'");
6502 return false;
6503 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006504 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006505 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006506 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006507 return false;
6508}
Jack Carterd76b2372013-03-21 21:44:16 +00006509
Daniel Sanders44934432014-08-07 12:03:36 +00006510bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006511 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006512 Parser.Lex();
6513
6514 // If this is not the end of the statement, report an error.
6515 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006516 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006517
6518 setFeatureBits(Mips::FeatureMSA, "msa");
6519 getTargetStreamer().emitDirectiveSetMsa();
6520 return false;
6521}
6522
6523bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006524 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006525 Parser.Lex();
6526
6527 // If this is not the end of the statement, report an error.
6528 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006529 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006530
6531 clearFeatureBits(Mips::FeatureMSA, "msa");
6532 getTargetStreamer().emitDirectiveSetNoMsa();
6533 return false;
6534}
6535
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006536bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006537 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006538 Parser.Lex(); // Eat "nodsp".
6539
6540 // If this is not the end of the statement, report an error.
6541 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6542 reportParseError("unexpected token, expected end of statement");
6543 return false;
6544 }
6545
6546 clearFeatureBits(Mips::FeatureDSP, "dsp");
6547 getTargetStreamer().emitDirectiveSetNoDsp();
6548 return false;
6549}
6550
Toma Tabacucc2502d2014-11-04 17:18:07 +00006551bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006552 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006553 Parser.Lex(); // Eat "mips16".
6554
Jack Carter39536722014-01-22 23:08:42 +00006555 // If this is not the end of the statement, report an error.
6556 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006557 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006558 return false;
6559 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006560
6561 setFeatureBits(Mips::FeatureMips16, "mips16");
6562 getTargetStreamer().emitDirectiveSetMips16();
6563 Parser.Lex(); // Consume the EndOfStatement.
6564 return false;
6565}
6566
6567bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006568 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006569 Parser.Lex(); // Eat "nomips16".
6570
6571 // If this is not the end of the statement, report an error.
6572 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6573 reportParseError("unexpected token, expected end of statement");
6574 return false;
6575 }
6576
6577 clearFeatureBits(Mips::FeatureMips16, "mips16");
6578 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006579 Parser.Lex(); // Consume the EndOfStatement.
6580 return false;
6581}
6582
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006583bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006584 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006585 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006586 // Line can be: .set fp=32
6587 // .set fp=xx
6588 // .set fp=64
6589 Parser.Lex(); // Eat fp token
6590 AsmToken Tok = Parser.getTok();
6591 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006592 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006593 return false;
6594 }
6595 Parser.Lex(); // Eat '=' token.
6596 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006597
6598 if (!parseFpABIValue(FpAbiVal, ".set"))
6599 return false;
6600
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006601 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006602 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006603 return false;
6604 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006605 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006606 Parser.Lex(); // Consume the EndOfStatement.
6607 return false;
6608}
6609
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006610bool MipsAsmParser::parseSetOddSPRegDirective() {
6611 MCAsmParser &Parser = getParser();
6612
6613 Parser.Lex(); // Eat "oddspreg".
6614 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6615 reportParseError("unexpected token, expected end of statement");
6616 return false;
6617 }
6618
6619 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6620 getTargetStreamer().emitDirectiveSetOddSPReg();
6621 return false;
6622}
6623
6624bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6625 MCAsmParser &Parser = getParser();
6626
6627 Parser.Lex(); // Eat "nooddspreg".
6628 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6629 reportParseError("unexpected token, expected end of statement");
6630 return false;
6631 }
6632
6633 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6634 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6635 return false;
6636}
6637
Simon Dardis805f1e02017-07-11 21:28:36 +00006638bool MipsAsmParser::parseSetMtDirective() {
6639 MCAsmParser &Parser = getParser();
6640 Parser.Lex(); // Eat "mt".
6641
6642 // If this is not the end of the statement, report an error.
6643 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6644 reportParseError("unexpected token, expected end of statement");
6645 return false;
6646 }
6647
6648 setFeatureBits(Mips::FeatureMT, "mt");
6649 getTargetStreamer().emitDirectiveSetMt();
6650 Parser.Lex(); // Consume the EndOfStatement.
6651 return false;
6652}
6653
6654bool MipsAsmParser::parseSetNoMtDirective() {
6655 MCAsmParser &Parser = getParser();
6656 Parser.Lex(); // Eat "nomt".
6657
6658 // If this is not the end of the statement, report an error.
6659 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6660 reportParseError("unexpected token, expected end of statement");
6661 return false;
6662 }
6663
6664 clearFeatureBits(Mips::FeatureMT, "mt");
6665
6666 getTargetStreamer().emitDirectiveSetNoMt();
6667 Parser.Lex(); // Consume the EndOfStatement.
6668 return false;
6669}
6670
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006671bool MipsAsmParser::parseSetNoCRCDirective() {
6672 MCAsmParser &Parser = getParser();
6673 Parser.Lex(); // Eat "nocrc".
6674
6675 // If this is not the end of the statement, report an error.
6676 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6677 reportParseError("unexpected token, expected end of statement");
6678 return false;
6679 }
6680
6681 clearFeatureBits(Mips::FeatureCRC, "crc");
6682
6683 getTargetStreamer().emitDirectiveSetNoCRC();
6684 Parser.Lex(); // Consume the EndOfStatement.
6685 return false;
6686}
6687
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006688bool MipsAsmParser::parseSetNoVirtDirective() {
6689 MCAsmParser &Parser = getParser();
6690 Parser.Lex(); // Eat "novirt".
6691
6692 // If this is not the end of the statement, report an error.
6693 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6694 reportParseError("unexpected token, expected end of statement");
6695 return false;
6696 }
6697
6698 clearFeatureBits(Mips::FeatureVirt, "virt");
6699
6700 getTargetStreamer().emitDirectiveSetNoVirt();
6701 Parser.Lex(); // Consume the EndOfStatement.
6702 return false;
6703}
6704
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006705bool MipsAsmParser::parseSetNoGINVDirective() {
6706 MCAsmParser &Parser = getParser();
6707 Parser.Lex(); // Eat "noginv".
6708
6709 // If this is not the end of the statement, report an error.
6710 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6711 reportParseError("unexpected token, expected end of statement");
6712 return false;
6713 }
6714
6715 clearFeatureBits(Mips::FeatureGINV, "ginv");
6716
6717 getTargetStreamer().emitDirectiveSetNoGINV();
6718 Parser.Lex(); // Consume the EndOfStatement.
6719 return false;
6720}
6721
Toma Tabacu9db22db2014-09-09 10:15:38 +00006722bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006723 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006724 SMLoc Loc = getLexer().getLoc();
6725
6726 Parser.Lex();
6727 if (getLexer().isNot(AsmToken::EndOfStatement))
6728 return reportParseError("unexpected token, expected end of statement");
6729
6730 // Always keep an element on the options "stack" to prevent the user
6731 // from changing the initial options. This is how we remember them.
6732 if (AssemblerOptions.size() == 2)
6733 return reportParseError(Loc, ".set pop with no .set push");
6734
Akira Hatanakab11ef082015-11-14 06:35:56 +00006735 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006736 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006737 setAvailableFeatures(
6738 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6739 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006740
6741 getTargetStreamer().emitDirectiveSetPop();
6742 return false;
6743}
6744
6745bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006746 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006747 Parser.Lex();
6748 if (getLexer().isNot(AsmToken::EndOfStatement))
6749 return reportParseError("unexpected token, expected end of statement");
6750
6751 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006752 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006753 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006754
6755 getTargetStreamer().emitDirectiveSetPush();
6756 return false;
6757}
6758
Toma Tabacu29696502015-06-02 09:48:04 +00006759bool MipsAsmParser::parseSetSoftFloatDirective() {
6760 MCAsmParser &Parser = getParser();
6761 Parser.Lex();
6762 if (getLexer().isNot(AsmToken::EndOfStatement))
6763 return reportParseError("unexpected token, expected end of statement");
6764
6765 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6766 getTargetStreamer().emitDirectiveSetSoftFloat();
6767 return false;
6768}
6769
6770bool MipsAsmParser::parseSetHardFloatDirective() {
6771 MCAsmParser &Parser = getParser();
6772 Parser.Lex();
6773 if (getLexer().isNot(AsmToken::EndOfStatement))
6774 return reportParseError("unexpected token, expected end of statement");
6775
6776 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6777 getTargetStreamer().emitDirectiveSetHardFloat();
6778 return false;
6779}
6780
Jack Carterd76b2372013-03-21 21:44:16 +00006781bool MipsAsmParser::parseSetAssignment() {
6782 StringRef Name;
6783 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006784 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006785
6786 if (Parser.parseIdentifier(Name))
Simon Atanasyan3535cb12018-05-29 09:51:22 +00006787 return reportParseError("expected identifier after .set");
Jack Carterd76b2372013-03-21 21:44:16 +00006788
6789 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006790 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006791 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006792
Simon Atanasyan69301c92018-05-29 15:58:06 +00006793 if (getLexer().is(AsmToken::Dollar) &&
6794 getLexer().peekTok().is(AsmToken::Integer)) {
6795 // Parse assignment of a numeric register:
6796 // .set r1,$1
6797 Parser.Lex(); // Eat $.
6798 RegisterSets[Name] = Parser.getTok();
6799 Parser.Lex(); // Eat identifier.
6800 getContext().getOrCreateSymbol(Name);
6801 } else if (!Parser.parseExpression(Value)) {
6802 // Parse assignment of an expression including
6803 // symbolic registers:
6804 // .set $tmp, $BB0-$BB1
6805 // .set r2, $f2
6806 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
6807 Sym->setVariableValue(Value);
6808 } else {
Jack Carter02593002013-05-28 22:21:05 +00006809 return reportParseError("expected valid expression after comma");
Simon Atanasyan69301c92018-05-29 15:58:06 +00006810 }
Jack Carterd76b2372013-03-21 21:44:16 +00006811
6812 return false;
6813}
Jack Carterd0bd6422013-04-18 00:41:53 +00006814
Toma Tabacu26647792014-09-09 12:52:14 +00006815bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006816 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006817 Parser.Lex();
6818 if (getLexer().isNot(AsmToken::EndOfStatement))
6819 return reportParseError("unexpected token, expected end of statement");
6820
6821 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006822 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006823 setAvailableFeatures(
6824 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6825 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006826 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6827
6828 getTargetStreamer().emitDirectiveSetMips0();
6829 return false;
6830}
6831
Toma Tabacu85618b32014-08-19 14:22:52 +00006832bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006833 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006834 Parser.Lex();
6835 if (getLexer().isNot(AsmToken::Equal))
6836 return reportParseError("unexpected token, expected equals sign");
6837
6838 Parser.Lex();
6839 StringRef Arch;
6840 if (Parser.parseIdentifier(Arch))
6841 return reportParseError("expected arch identifier");
6842
6843 StringRef ArchFeatureName =
6844 StringSwitch<StringRef>(Arch)
6845 .Case("mips1", "mips1")
6846 .Case("mips2", "mips2")
6847 .Case("mips3", "mips3")
6848 .Case("mips4", "mips4")
6849 .Case("mips5", "mips5")
6850 .Case("mips32", "mips32")
6851 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006852 .Case("mips32r3", "mips32r3")
6853 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006854 .Case("mips32r6", "mips32r6")
6855 .Case("mips64", "mips64")
6856 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006857 .Case("mips64r3", "mips64r3")
6858 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006859 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006860 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006861 .Case("r4000", "mips3") // This is an implementation of Mips3.
6862 .Default("");
6863
6864 if (ArchFeatureName.empty())
6865 return reportParseError("unsupported architecture");
6866
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006867 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6868 return reportParseError("mips64r6 does not support microMIPS");
6869
Toma Tabacu85618b32014-08-19 14:22:52 +00006870 selectArch(ArchFeatureName);
6871 getTargetStreamer().emitDirectiveSetArch(Arch);
6872 return false;
6873}
6874
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006875bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006876 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006877 Parser.Lex();
6878 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006879 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006880
Matheus Almeida2852af82014-04-22 10:15:54 +00006881 switch (Feature) {
6882 default:
6883 llvm_unreachable("Unimplemented feature");
6884 case Mips::FeatureDSP:
6885 setFeatureBits(Mips::FeatureDSP, "dsp");
6886 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006887 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006888 case Mips::FeatureDSPR2:
6889 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6890 getTargetStreamer().emitDirectiveSetDspr2();
6891 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006892 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006893 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006894 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006895 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006896 case Mips::FeatureMips1:
6897 selectArch("mips1");
6898 getTargetStreamer().emitDirectiveSetMips1();
6899 break;
6900 case Mips::FeatureMips2:
6901 selectArch("mips2");
6902 getTargetStreamer().emitDirectiveSetMips2();
6903 break;
6904 case Mips::FeatureMips3:
6905 selectArch("mips3");
6906 getTargetStreamer().emitDirectiveSetMips3();
6907 break;
6908 case Mips::FeatureMips4:
6909 selectArch("mips4");
6910 getTargetStreamer().emitDirectiveSetMips4();
6911 break;
6912 case Mips::FeatureMips5:
6913 selectArch("mips5");
6914 getTargetStreamer().emitDirectiveSetMips5();
6915 break;
6916 case Mips::FeatureMips32:
6917 selectArch("mips32");
6918 getTargetStreamer().emitDirectiveSetMips32();
6919 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006920 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006921 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006922 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006923 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006924 case Mips::FeatureMips32r3:
6925 selectArch("mips32r3");
6926 getTargetStreamer().emitDirectiveSetMips32R3();
6927 break;
6928 case Mips::FeatureMips32r5:
6929 selectArch("mips32r5");
6930 getTargetStreamer().emitDirectiveSetMips32R5();
6931 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006932 case Mips::FeatureMips32r6:
6933 selectArch("mips32r6");
6934 getTargetStreamer().emitDirectiveSetMips32R6();
6935 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006936 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006937 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006938 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006939 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006940 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006941 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006942 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006943 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006944 case Mips::FeatureMips64r3:
6945 selectArch("mips64r3");
6946 getTargetStreamer().emitDirectiveSetMips64R3();
6947 break;
6948 case Mips::FeatureMips64r5:
6949 selectArch("mips64r5");
6950 getTargetStreamer().emitDirectiveSetMips64R5();
6951 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006952 case Mips::FeatureMips64r6:
6953 selectArch("mips64r6");
6954 getTargetStreamer().emitDirectiveSetMips64R6();
6955 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006956 case Mips::FeatureCRC:
6957 setFeatureBits(Mips::FeatureCRC, "crc");
6958 getTargetStreamer().emitDirectiveSetCRC();
6959 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006960 case Mips::FeatureVirt:
6961 setFeatureBits(Mips::FeatureVirt, "virt");
6962 getTargetStreamer().emitDirectiveSetVirt();
6963 break;
Petar Jovanovicdaf51692018-05-17 16:30:32 +00006964 case Mips::FeatureGINV:
6965 setFeatureBits(Mips::FeatureGINV, "ginv");
6966 getTargetStreamer().emitDirectiveSetGINV();
6967 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006968 }
6969 return false;
6970}
6971
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006972bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006973 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006974 if (getLexer().isNot(AsmToken::Comma)) {
6975 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006976 return Error(Loc, ErrorStr);
6977 }
6978
Matheus Almeida2852af82014-04-22 10:15:54 +00006979 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006980 return true;
6981}
6982
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006983// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6984// In this class, it is only used for .cprestore.
6985// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6986// MipsTargetELFStreamer and MipsAsmParser.
6987bool MipsAsmParser::isPicAndNotNxxAbi() {
6988 return inPicMode() && !(isABI_N32() || isABI_N64());
6989}
6990
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006991bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006992 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006993 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006994
Toma Tabacudde4c462014-11-06 10:02:45 +00006995 if (inMips16Mode()) {
6996 reportParseError(".cpload is not supported in Mips16 mode");
6997 return false;
6998 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006999
David Blaikie960ea3f2014-06-08 16:18:35 +00007000 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007001 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007002 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7003 reportParseError("expected register containing function address");
7004 return false;
7005 }
7006
David Blaikie960ea3f2014-06-08 16:18:35 +00007007 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7008 if (!RegOpnd.isGPRAsmReg()) {
7009 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007010 return false;
7011 }
7012
Toma Tabacudde4c462014-11-06 10:02:45 +00007013 // If this is not the end of the statement, report an error.
7014 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7015 reportParseError("unexpected token, expected end of statement");
7016 return false;
7017 }
7018
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007019 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007020 return false;
7021}
7022
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007023bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7024 MCAsmParser &Parser = getParser();
7025
7026 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7027 // is used in non-PIC mode.
7028
7029 if (inMips16Mode()) {
7030 reportParseError(".cprestore is not supported in Mips16 mode");
7031 return false;
7032 }
7033
7034 // Get the stack offset value.
7035 const MCExpr *StackOffset;
7036 int64_t StackOffsetVal;
7037 if (Parser.parseExpression(StackOffset)) {
7038 reportParseError("expected stack offset value");
7039 return false;
7040 }
7041
7042 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7043 reportParseError("stack offset is not an absolute expression");
7044 return false;
7045 }
7046
7047 if (StackOffsetVal < 0) {
7048 Warning(Loc, ".cprestore with negative stack offset has no effect");
7049 IsCpRestoreSet = false;
7050 } else {
7051 IsCpRestoreSet = true;
7052 CpRestoreOffset = StackOffsetVal;
7053 }
7054
7055 // If this is not the end of the statement, report an error.
7056 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7057 reportParseError("unexpected token, expected end of statement");
7058 return false;
7059 }
7060
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007061 if (!getTargetStreamer().emitDirectiveCpRestore(
7062 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007063 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007064 Parser.Lex(); // Consume the EndOfStatement.
7065 return false;
7066}
7067
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007068bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007069 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007070 unsigned FuncReg;
7071 unsigned Save;
7072 bool SaveIsReg = true;
7073
Matheus Almeida7e815762014-06-18 13:08:59 +00007074 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007075 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007076 if (ResTy == MatchOperand_NoMatch) {
7077 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007078 return false;
7079 }
7080
7081 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7082 if (!FuncRegOpnd.isGPRAsmReg()) {
7083 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007084 return false;
7085 }
7086
7087 FuncReg = FuncRegOpnd.getGPR32Reg();
7088 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007089
Toma Tabacu65f10572014-09-16 15:00:52 +00007090 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007091 return true;
7092
Toma Tabacu13964452014-09-04 13:23:44 +00007093 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007094 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007095 const MCExpr *OffsetExpr;
7096 int64_t OffsetVal;
7097 SMLoc ExprLoc = getLexer().getLoc();
7098
7099 if (Parser.parseExpression(OffsetExpr) ||
7100 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7101 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007102 return false;
7103 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007104
7105 Save = OffsetVal;
7106 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007107 } else {
7108 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7109 if (!SaveOpnd.isGPRAsmReg()) {
7110 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007111 return false;
7112 }
7113 Save = SaveOpnd.getGPR32Reg();
7114 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007115
Toma Tabacu65f10572014-09-16 15:00:52 +00007116 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007117 return true;
7118
Toma Tabacu8874eac2015-02-18 13:46:53 +00007119 const MCExpr *Expr;
7120 if (Parser.parseExpression(Expr)) {
7121 reportParseError("expected expression");
7122 return false;
7123 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007124
Toma Tabacu8874eac2015-02-18 13:46:53 +00007125 if (Expr->getKind() != MCExpr::SymbolRef) {
7126 reportParseError("expected symbol");
7127 return false;
7128 }
7129 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7130
Daniel Sandersf173dda2015-09-22 10:50:09 +00007131 CpSaveLocation = Save;
7132 CpSaveLocationIsRegister = SaveIsReg;
7133
Toma Tabacu8874eac2015-02-18 13:46:53 +00007134 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7135 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007136 return false;
7137}
7138
Daniel Sandersf173dda2015-09-22 10:50:09 +00007139bool MipsAsmParser::parseDirectiveCPReturn() {
7140 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7141 CpSaveLocationIsRegister);
7142 return false;
7143}
7144
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007145bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007146 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007147 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7148 const AsmToken &Tok = Parser.getTok();
7149
7150 if (Tok.getString() == "2008") {
7151 Parser.Lex();
7152 getTargetStreamer().emitDirectiveNaN2008();
7153 return false;
7154 } else if (Tok.getString() == "legacy") {
7155 Parser.Lex();
7156 getTargetStreamer().emitDirectiveNaNLegacy();
7157 return false;
7158 }
7159 }
7160 // If we don't recognize the option passed to the .nan
7161 // directive (e.g. no option or unknown option), emit an error.
7162 reportParseError("invalid option in .nan directive");
7163 return false;
7164}
7165
Jack Carter0b744b32012-10-04 02:29:46 +00007166bool MipsAsmParser::parseDirectiveSet() {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007167 const AsmToken &Tok = getParser().getTok();
7168 StringRef IdVal = Tok.getString();
7169 SMLoc Loc = Tok.getLoc();
Jack Carter0b744b32012-10-04 02:29:46 +00007170
Simon Atanasyand408ec42018-05-29 09:51:28 +00007171 if (IdVal == "noat")
Jack Carter0b744b32012-10-04 02:29:46 +00007172 return parseSetNoAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007173 if (IdVal == "at")
Jack Carter0b744b32012-10-04 02:29:46 +00007174 return parseSetAtDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007175 if (IdVal == "arch")
Toma Tabacu85618b32014-08-19 14:22:52 +00007176 return parseSetArchDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007177 if (IdVal == "bopt") {
7178 Warning(Loc, "'bopt' feature is unsupported");
Simon Dardisac9c30c2017-02-01 18:50:24 +00007179 getParser().Lex();
7180 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007181 }
7182 if (IdVal == "nobopt") {
Simon Dardisac9c30c2017-02-01 18:50:24 +00007183 // We're already running in nobopt mode, so nothing to do.
7184 getParser().Lex();
7185 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007186 }
7187 if (IdVal == "fp")
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007188 return parseSetFpDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007189 if (IdVal == "oddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007190 return parseSetOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007191 if (IdVal == "nooddspreg")
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007192 return parseSetNoOddSPRegDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007193 if (IdVal == "pop")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007194 return parseSetPopDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007195 if (IdVal == "push")
Toma Tabacu9db22db2014-09-09 10:15:38 +00007196 return parseSetPushDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007197 if (IdVal == "reorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007198 return parseSetReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007199 if (IdVal == "noreorder")
Jack Carter0b744b32012-10-04 02:29:46 +00007200 return parseSetNoReorderDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007201 if (IdVal == "macro")
Jack Carter0b744b32012-10-04 02:29:46 +00007202 return parseSetMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007203 if (IdVal == "nomacro")
Jack Carter0b744b32012-10-04 02:29:46 +00007204 return parseSetNoMacroDirective();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007205 if (IdVal == "mips16")
Toma Tabacucc2502d2014-11-04 17:18:07 +00007206 return parseSetMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007207 if (IdVal == "nomips16")
Jack Carter39536722014-01-22 23:08:42 +00007208 return parseSetNoMips16Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007209 if (IdVal == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007210 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007211 getTargetStreamer().emitDirectiveSetNoMicroMips();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007212 getParser().eatToEndOfStatement();
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007213 return false;
Simon Atanasyand408ec42018-05-29 09:51:28 +00007214 }
7215 if (IdVal == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007216 if (hasMips64r6()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007217 Error(Loc, ".set micromips directive is not supported with MIPS64R6");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007218 return false;
7219 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007220 return parseSetFeature(Mips::FeatureMicroMips);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007221 }
7222 if (IdVal == "mips0")
Toma Tabacu26647792014-09-09 12:52:14 +00007223 return parseSetMips0Directive();
Simon Atanasyand408ec42018-05-29 09:51:28 +00007224 if (IdVal == "mips1")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007225 return parseSetFeature(Mips::FeatureMips1);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007226 if (IdVal == "mips2")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007227 return parseSetFeature(Mips::FeatureMips2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007228 if (IdVal == "mips3")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007229 return parseSetFeature(Mips::FeatureMips3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007230 if (IdVal == "mips4")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007231 return parseSetFeature(Mips::FeatureMips4);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007232 if (IdVal == "mips5")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007233 return parseSetFeature(Mips::FeatureMips5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007234 if (IdVal == "mips32")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007235 return parseSetFeature(Mips::FeatureMips32);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007236 if (IdVal == "mips32r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007237 return parseSetFeature(Mips::FeatureMips32r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007238 if (IdVal == "mips32r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007239 return parseSetFeature(Mips::FeatureMips32r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007240 if (IdVal == "mips32r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007241 return parseSetFeature(Mips::FeatureMips32r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007242 if (IdVal == "mips32r6")
Daniel Sandersf0df2212014-08-04 12:20:00 +00007243 return parseSetFeature(Mips::FeatureMips32r6);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007244 if (IdVal == "mips64")
Matheus Almeida2852af82014-04-22 10:15:54 +00007245 return parseSetFeature(Mips::FeatureMips64);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007246 if (IdVal == "mips64r2")
Matheus Almeida2852af82014-04-22 10:15:54 +00007247 return parseSetFeature(Mips::FeatureMips64r2);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007248 if (IdVal == "mips64r3")
Daniel Sanders17793142015-02-18 16:24:50 +00007249 return parseSetFeature(Mips::FeatureMips64r3);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007250 if (IdVal == "mips64r5")
Daniel Sanders17793142015-02-18 16:24:50 +00007251 return parseSetFeature(Mips::FeatureMips64r5);
Simon Atanasyand408ec42018-05-29 09:51:28 +00007252 if (IdVal == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007253 if (inMicroMipsMode()) {
Simon Atanasyand408ec42018-05-29 09:51:28 +00007254 Error(Loc, "MIPS64R6 is not supported with microMIPS");
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007255 return false;
7256 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007257 return parseSetFeature(Mips::FeatureMips64r6);
Jack Carter0b744b32012-10-04 02:29:46 +00007258 }
Simon Atanasyand408ec42018-05-29 09:51:28 +00007259 if (IdVal == "dsp")
7260 return parseSetFeature(Mips::FeatureDSP);
7261 if (IdVal == "dspr2")
7262 return parseSetFeature(Mips::FeatureDSPR2);
7263 if (IdVal == "nodsp")
7264 return parseSetNoDspDirective();
7265 if (IdVal == "msa")
7266 return parseSetMsaDirective();
7267 if (IdVal == "nomsa")
7268 return parseSetNoMsaDirective();
7269 if (IdVal == "mt")
7270 return parseSetMtDirective();
7271 if (IdVal == "nomt")
7272 return parseSetNoMtDirective();
7273 if (IdVal == "softfloat")
7274 return parseSetSoftFloatDirective();
7275 if (IdVal == "hardfloat")
7276 return parseSetHardFloatDirective();
7277 if (IdVal == "crc")
7278 return parseSetFeature(Mips::FeatureCRC);
7279 if (IdVal == "nocrc")
7280 return parseSetNoCRCDirective();
7281 if (IdVal == "virt")
7282 return parseSetFeature(Mips::FeatureVirt);
7283 if (IdVal == "novirt")
7284 return parseSetNoVirtDirective();
7285 if (IdVal == "ginv")
7286 return parseSetFeature(Mips::FeatureGINV);
7287 if (IdVal == "noginv")
7288 return parseSetNoGINVDirective();
Jack Carter07c818d2013-01-25 01:31:34 +00007289
Simon Atanasyand408ec42018-05-29 09:51:28 +00007290 // It is just an identifier, look for an assignment.
7291 return parseSetAssignment();
Jack Carter0b744b32012-10-04 02:29:46 +00007292}
7293
Vladimir Medic4c299852013-11-06 11:27:05 +00007294/// parseDirectiveGpWord
7295/// ::= .gpword local_sym
7296bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007297 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007298 const MCExpr *Value;
7299 // EmitGPRel32Value requires an expression, so we are using base class
7300 // method to evaluate the expression.
7301 if (getParser().parseExpression(Value))
7302 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007303 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007304
Vladimir Medice10c1122013-11-13 13:18:04 +00007305 if (getLexer().isNot(AsmToken::EndOfStatement))
Fangrui Songf78650a2018-07-30 19:41:25 +00007306 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007307 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007308 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007309 return false;
7310}
7311
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007312/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007313/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007314bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007315 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007316 const MCExpr *Value;
7317 // EmitGPRel64Value requires an expression, so we are using base class
7318 // method to evaluate the expression.
7319 if (getParser().parseExpression(Value))
7320 return true;
7321 getParser().getStreamer().EmitGPRel64Value(Value);
7322
7323 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007324 return Error(getLexer().getLoc(),
7325 "unexpected token, expected end of statement");
7326 Parser.Lex(); // Eat EndOfStatement token.
7327 return false;
7328}
7329
7330/// parseDirectiveDtpRelWord
7331/// ::= .dtprelword tls_sym
7332bool MipsAsmParser::parseDirectiveDtpRelWord() {
7333 MCAsmParser &Parser = getParser();
7334 const MCExpr *Value;
7335 // EmitDTPRel32Value requires an expression, so we are using base class
7336 // method to evaluate the expression.
7337 if (getParser().parseExpression(Value))
7338 return true;
7339 getParser().getStreamer().EmitDTPRel32Value(Value);
7340
7341 if (getLexer().isNot(AsmToken::EndOfStatement))
7342 return Error(getLexer().getLoc(),
7343 "unexpected token, expected end of statement");
7344 Parser.Lex(); // Eat EndOfStatement token.
7345 return false;
7346}
7347
7348/// parseDirectiveDtpRelDWord
7349/// ::= .dtpreldword tls_sym
7350bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7351 MCAsmParser &Parser = getParser();
7352 const MCExpr *Value;
7353 // EmitDTPRel64Value requires an expression, so we are using base class
7354 // method to evaluate the expression.
7355 if (getParser().parseExpression(Value))
7356 return true;
7357 getParser().getStreamer().EmitDTPRel64Value(Value);
7358
7359 if (getLexer().isNot(AsmToken::EndOfStatement))
7360 return Error(getLexer().getLoc(),
7361 "unexpected token, expected end of statement");
7362 Parser.Lex(); // Eat EndOfStatement token.
7363 return false;
7364}
7365
7366/// parseDirectiveTpRelWord
7367/// ::= .tprelword tls_sym
7368bool MipsAsmParser::parseDirectiveTpRelWord() {
7369 MCAsmParser &Parser = getParser();
7370 const MCExpr *Value;
7371 // EmitTPRel32Value requires an expression, so we are using base class
7372 // method to evaluate the expression.
7373 if (getParser().parseExpression(Value))
7374 return true;
7375 getParser().getStreamer().EmitTPRel32Value(Value);
7376
7377 if (getLexer().isNot(AsmToken::EndOfStatement))
7378 return Error(getLexer().getLoc(),
7379 "unexpected token, expected end of statement");
7380 Parser.Lex(); // Eat EndOfStatement token.
7381 return false;
7382}
7383
7384/// parseDirectiveTpRelDWord
7385/// ::= .tpreldword tls_sym
7386bool MipsAsmParser::parseDirectiveTpRelDWord() {
7387 MCAsmParser &Parser = getParser();
7388 const MCExpr *Value;
7389 // EmitTPRel64Value requires an expression, so we are using base class
7390 // method to evaluate the expression.
7391 if (getParser().parseExpression(Value))
7392 return true;
7393 getParser().getStreamer().EmitTPRel64Value(Value);
7394
7395 if (getLexer().isNot(AsmToken::EndOfStatement))
7396 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007397 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007398 Parser.Lex(); // Eat EndOfStatement token.
7399 return false;
7400}
7401
Jack Carter0cd3c192014-01-06 23:27:31 +00007402bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007403 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007404 // Get the option token.
7405 AsmToken Tok = Parser.getTok();
7406 // At the moment only identifiers are supported.
7407 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007408 return Error(Parser.getTok().getLoc(),
7409 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007410 }
7411
7412 StringRef Option = Tok.getIdentifier();
7413
7414 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007415 // MipsAsmParser needs to know if the current PIC mode changes.
7416 IsPicEnabled = false;
7417
Jack Carter0cd3c192014-01-06 23:27:31 +00007418 getTargetStreamer().emitDirectiveOptionPic0();
7419 Parser.Lex();
7420 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007421 return Error(Parser.getTok().getLoc(),
7422 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007423 }
7424 return false;
7425 }
7426
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007427 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007428 // MipsAsmParser needs to know if the current PIC mode changes.
7429 IsPicEnabled = true;
7430
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007431 getTargetStreamer().emitDirectiveOptionPic2();
7432 Parser.Lex();
7433 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007434 return Error(Parser.getTok().getLoc(),
7435 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007436 }
7437 return false;
7438 }
7439
Jack Carter0cd3c192014-01-06 23:27:31 +00007440 // Unknown option.
Fangrui Songf78650a2018-07-30 19:41:25 +00007441 Warning(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007442 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007443 Parser.eatToEndOfStatement();
7444 return false;
7445}
7446
Toma Tabacu9ca50962015-04-16 09:53:47 +00007447/// parseInsnDirective
7448/// ::= .insn
7449bool MipsAsmParser::parseInsnDirective() {
7450 // If this is not the end of the statement, report an error.
7451 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7452 reportParseError("unexpected token, expected end of statement");
7453 return false;
7454 }
7455
7456 // The actual label marking happens in
7457 // MipsELFStreamer::createPendingLabelRelocs().
7458 getTargetStreamer().emitDirectiveInsn();
7459
7460 getParser().Lex(); // Eat EndOfStatement token.
7461 return false;
7462}
7463
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007464/// parseRSectionDirective
7465/// ::= .rdata
7466bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7467 // If this is not the end of the statement, report an error.
7468 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7469 reportParseError("unexpected token, expected end of statement");
7470 return false;
7471 }
7472
7473 MCSection *ELFSection = getContext().getELFSection(
7474 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7475 getParser().getStreamer().SwitchSection(ELFSection);
7476
7477 getParser().Lex(); // Eat EndOfStatement token.
7478 return false;
7479}
7480
Simon Atanasyanbe186202016-02-11 06:45:54 +00007481/// parseSSectionDirective
7482/// ::= .sbss
7483/// ::= .sdata
7484bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7485 // If this is not the end of the statement, report an error.
7486 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7487 reportParseError("unexpected token, expected end of statement");
7488 return false;
7489 }
7490
7491 MCSection *ELFSection = getContext().getELFSection(
7492 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7493 getParser().getStreamer().SwitchSection(ELFSection);
7494
7495 getParser().Lex(); // Eat EndOfStatement token.
7496 return false;
7497}
7498
Daniel Sanders7e527422014-07-10 13:38:23 +00007499/// parseDirectiveModule
7500/// ::= .module oddspreg
7501/// ::= .module nooddspreg
7502/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007503/// ::= .module softfloat
7504/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007505/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007506/// ::= .module crc
7507/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007508/// ::= .module virt
7509/// ::= .module novirt
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007510/// ::= .module ginv
7511/// ::= .module noginv
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007512bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007513 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007514 MCAsmLexer &Lexer = getLexer();
7515 SMLoc L = Lexer.getLoc();
7516
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007517 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007518 // TODO : get a better message.
7519 reportParseError(".module directive must appear before any code");
7520 return false;
7521 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007522
Toma Tabacuc405c822015-01-23 10:40:19 +00007523 StringRef Option;
7524 if (Parser.parseIdentifier(Option)) {
7525 reportParseError("expected .module option identifier");
7526 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007527 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007528
Toma Tabacuc405c822015-01-23 10:40:19 +00007529 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007530 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007531
Toma Tabacu3c499582015-06-25 10:56:57 +00007532 // Synchronize the abiflags information with the FeatureBits information we
7533 // changed above.
7534 getTargetStreamer().updateABIInfo(*this);
7535
7536 // If printing assembly, use the recently updated abiflags information.
7537 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7538 // emitted at the end).
7539 getTargetStreamer().emitDirectiveModuleOddSPReg();
7540
Toma Tabacuc405c822015-01-23 10:40:19 +00007541 // If this is not the end of the statement, report an error.
7542 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7543 reportParseError("unexpected token, expected end of statement");
7544 return false;
7545 }
7546
7547 return false; // parseDirectiveModule has finished successfully.
7548 } else if (Option == "nooddspreg") {
7549 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007550 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007551 }
7552
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007553 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007554
Toma Tabacu3c499582015-06-25 10:56:57 +00007555 // Synchronize the abiflags information with the FeatureBits information we
7556 // changed above.
7557 getTargetStreamer().updateABIInfo(*this);
7558
7559 // If printing assembly, use the recently updated abiflags information.
7560 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7561 // emitted at the end).
7562 getTargetStreamer().emitDirectiveModuleOddSPReg();
7563
Toma Tabacuc405c822015-01-23 10:40:19 +00007564 // If this is not the end of the statement, report an error.
7565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7566 reportParseError("unexpected token, expected end of statement");
7567 return false;
7568 }
7569
7570 return false; // parseDirectiveModule has finished successfully.
7571 } else if (Option == "fp") {
7572 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007573 } else if (Option == "softfloat") {
7574 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7575
7576 // Synchronize the ABI Flags information with the FeatureBits information we
7577 // updated above.
7578 getTargetStreamer().updateABIInfo(*this);
7579
7580 // If printing assembly, use the recently updated ABI Flags information.
7581 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7582 // emitted later).
7583 getTargetStreamer().emitDirectiveModuleSoftFloat();
7584
7585 // If this is not the end of the statement, report an error.
7586 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7587 reportParseError("unexpected token, expected end of statement");
7588 return false;
7589 }
7590
7591 return false; // parseDirectiveModule has finished successfully.
7592 } else if (Option == "hardfloat") {
7593 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7594
7595 // Synchronize the ABI Flags information with the FeatureBits information we
7596 // updated above.
7597 getTargetStreamer().updateABIInfo(*this);
7598
7599 // If printing assembly, use the recently updated ABI Flags information.
7600 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7601 // emitted later).
7602 getTargetStreamer().emitDirectiveModuleHardFloat();
7603
7604 // If this is not the end of the statement, report an error.
7605 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7606 reportParseError("unexpected token, expected end of statement");
7607 return false;
7608 }
7609
7610 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007611 } else if (Option == "mt") {
7612 setModuleFeatureBits(Mips::FeatureMT, "mt");
7613
7614 // Synchronize the ABI Flags information with the FeatureBits information we
7615 // updated above.
7616 getTargetStreamer().updateABIInfo(*this);
7617
Simon Dardisd9611922017-07-11 21:36:58 +00007618 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007619 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7620 // emitted later).
7621 getTargetStreamer().emitDirectiveModuleMT();
7622
7623 // If this is not the end of the statement, report an error.
7624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7625 reportParseError("unexpected token, expected end of statement");
7626 return false;
7627 }
7628
7629 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007630 } else if (Option == "crc") {
7631 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7632
7633 // Synchronize the ABI Flags information with the FeatureBits information we
7634 // updated above.
7635 getTargetStreamer().updateABIInfo(*this);
7636
7637 // If printing assembly, use the recently updated ABI Flags information.
7638 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7639 // emitted later).
7640 getTargetStreamer().emitDirectiveModuleCRC();
7641
7642 // If this is not the end of the statement, report an error.
7643 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7644 reportParseError("unexpected token, expected end of statement");
7645 return false;
7646 }
7647
7648 return false; // parseDirectiveModule has finished successfully.
7649 } else if (Option == "nocrc") {
7650 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7651
7652 // Synchronize the ABI Flags information with the FeatureBits information we
7653 // updated above.
7654 getTargetStreamer().updateABIInfo(*this);
7655
7656 // If printing assembly, use the recently updated ABI Flags information.
7657 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7658 // emitted later).
7659 getTargetStreamer().emitDirectiveModuleNoCRC();
7660
7661 // If this is not the end of the statement, report an error.
7662 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7663 reportParseError("unexpected token, expected end of statement");
7664 return false;
7665 }
7666
7667 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007668 } else if (Option == "virt") {
7669 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7670
7671 // Synchronize the ABI Flags information with the FeatureBits information we
7672 // updated above.
7673 getTargetStreamer().updateABIInfo(*this);
7674
7675 // If printing assembly, use the recently updated ABI Flags information.
7676 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7677 // emitted later).
7678 getTargetStreamer().emitDirectiveModuleVirt();
7679
7680 // If this is not the end of the statement, report an error.
7681 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7682 reportParseError("unexpected token, expected end of statement");
7683 return false;
7684 }
7685
7686 return false; // parseDirectiveModule has finished successfully.
7687 } else if (Option == "novirt") {
7688 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7689
7690 // Synchronize the ABI Flags information with the FeatureBits information we
7691 // updated above.
7692 getTargetStreamer().updateABIInfo(*this);
7693
7694 // If printing assembly, use the recently updated ABI Flags information.
7695 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7696 // emitted later).
7697 getTargetStreamer().emitDirectiveModuleNoVirt();
7698
7699 // If this is not the end of the statement, report an error.
7700 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7701 reportParseError("unexpected token, expected end of statement");
7702 return false;
7703 }
7704
7705 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicdaf51692018-05-17 16:30:32 +00007706 } else if (Option == "ginv") {
7707 setModuleFeatureBits(Mips::FeatureGINV, "ginv");
7708
7709 // Synchronize the ABI Flags information with the FeatureBits information we
7710 // updated above.
7711 getTargetStreamer().updateABIInfo(*this);
7712
7713 // If printing assembly, use the recently updated ABI Flags information.
7714 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7715 // emitted later).
7716 getTargetStreamer().emitDirectiveModuleGINV();
7717
7718 // If this is not the end of the statement, report an error.
7719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7720 reportParseError("unexpected token, expected end of statement");
7721 return false;
7722 }
7723
7724 return false; // parseDirectiveModule has finished successfully.
7725 } else if (Option == "noginv") {
7726 clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
7727
7728 // Synchronize the ABI Flags information with the FeatureBits information we
7729 // updated above.
7730 getTargetStreamer().updateABIInfo(*this);
7731
7732 // If printing assembly, use the recently updated ABI Flags information.
7733 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7734 // emitted later).
7735 getTargetStreamer().emitDirectiveModuleNoGINV();
7736
7737 // If this is not the end of the statement, report an error.
7738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7739 reportParseError("unexpected token, expected end of statement");
7740 return false;
7741 }
7742
7743 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007744 } else {
7745 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7746 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007747}
7748
7749/// parseDirectiveModuleFP
7750/// ::= =32
7751/// ::= =xx
7752/// ::= =64
7753bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007754 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007755 MCAsmLexer &Lexer = getLexer();
7756
7757 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007758 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007759 return false;
7760 }
7761 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007762
Daniel Sanders7e527422014-07-10 13:38:23 +00007763 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007764 if (!parseFpABIValue(FpABI, ".module"))
7765 return false;
7766
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007767 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007768 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007769 return false;
7770 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007771
Toma Tabacua64e5402015-06-25 12:44:38 +00007772 // Synchronize the abiflags information with the FeatureBits information we
7773 // changed above.
7774 getTargetStreamer().updateABIInfo(*this);
7775
7776 // If printing assembly, use the recently updated abiflags information.
7777 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7778 // emitted at the end).
7779 getTargetStreamer().emitDirectiveModuleFP();
7780
Daniel Sanders7e527422014-07-10 13:38:23 +00007781 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007782 return false;
7783}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007784
Daniel Sanders7e527422014-07-10 13:38:23 +00007785bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007786 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007787 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007788 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007789 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007790
7791 if (Lexer.is(AsmToken::Identifier)) {
7792 StringRef Value = Parser.getTok().getString();
7793 Parser.Lex();
7794
7795 if (Value != "xx") {
7796 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7797 return false;
7798 }
7799
7800 if (!isABI_O32()) {
7801 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7802 return false;
7803 }
7804
Daniel Sanders7e527422014-07-10 13:38:23 +00007805 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007806 if (ModuleLevelOptions) {
7807 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7808 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7809 } else {
7810 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7811 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7812 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007813 return true;
7814 }
7815
7816 if (Lexer.is(AsmToken::Integer)) {
7817 unsigned Value = Parser.getTok().getIntVal();
7818 Parser.Lex();
7819
7820 if (Value != 32 && Value != 64) {
7821 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7822 return false;
7823 }
7824
7825 if (Value == 32) {
7826 if (!isABI_O32()) {
7827 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7828 return false;
7829 }
7830
Daniel Sanders7e527422014-07-10 13:38:23 +00007831 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007832 if (ModuleLevelOptions) {
7833 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7834 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7835 } else {
7836 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7837 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7838 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007839 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007840 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007841 if (ModuleLevelOptions) {
7842 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7843 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7844 } else {
7845 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7846 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7847 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007848 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007849
Daniel Sanders7e527422014-07-10 13:38:23 +00007850 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007851 }
7852
7853 return false;
7854}
7855
Jack Carter0b744b32012-10-04 02:29:46 +00007856bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007857 // This returns false if this function recognizes the directive
7858 // regardless of whether it is successfully handles or reports an
7859 // error. Otherwise it returns true to give the generic parser a
7860 // chance at recognizing it.
7861
Rafael Espindola961d4692014-11-11 05:18:41 +00007862 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007863 StringRef IDVal = DirectiveID.getString();
7864
Nirav Dave996fc132016-05-05 14:15:46 +00007865 if (IDVal == ".cpload") {
7866 parseDirectiveCpLoad(DirectiveID.getLoc());
7867 return false;
7868 }
7869 if (IDVal == ".cprestore") {
7870 parseDirectiveCpRestore(DirectiveID.getLoc());
7871 return false;
7872 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007873 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007874 StringRef SymbolName;
7875
7876 if (Parser.parseIdentifier(SymbolName)) {
7877 reportParseError("expected identifier after .ent");
7878 return false;
7879 }
7880
7881 // There's an undocumented extension that allows an integer to
7882 // follow the name of the procedure which AFAICS is ignored by GAS.
7883 // Example: .ent foo,2
7884 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7885 if (getLexer().isNot(AsmToken::Comma)) {
7886 // Even though we accept this undocumented extension for compatibility
7887 // reasons, the additional integer argument does not actually change
7888 // the behaviour of the '.ent' directive, so we would like to discourage
7889 // its use. We do this by not referring to the extended version in
7890 // error messages which are not directly related to its use.
7891 reportParseError("unexpected token, expected end of statement");
7892 return false;
7893 }
7894 Parser.Lex(); // Eat the comma.
7895 const MCExpr *DummyNumber;
7896 int64_t DummyNumberVal;
7897 // If the user was explicitly trying to use the extended version,
7898 // we still give helpful extension-related error messages.
7899 if (Parser.parseExpression(DummyNumber)) {
7900 reportParseError("expected number after comma");
7901 return false;
7902 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007903 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007904 reportParseError("expected an absolute expression after comma");
7905 return false;
7906 }
7907 }
7908
7909 // If this is not the end of the statement, report an error.
7910 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7911 reportParseError("unexpected token, expected end of statement");
7912 return false;
7913 }
7914
Jim Grosbach6f482002015-05-18 18:43:14 +00007915 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007916
7917 getTargetStreamer().emitDirectiveEnt(*Sym);
7918 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007919 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007920 return false;
7921 }
7922
Jack Carter07c818d2013-01-25 01:31:34 +00007923 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007924 StringRef SymbolName;
7925
7926 if (Parser.parseIdentifier(SymbolName)) {
7927 reportParseError("expected identifier after .end");
7928 return false;
7929 }
7930
7931 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7932 reportParseError("unexpected token, expected end of statement");
7933 return false;
7934 }
7935
7936 if (CurrentFn == nullptr) {
7937 reportParseError(".end used without .ent");
7938 return false;
7939 }
7940
7941 if ((SymbolName != CurrentFn->getName())) {
7942 reportParseError(".end symbol does not match .ent symbol");
7943 return false;
7944 }
7945
7946 getTargetStreamer().emitDirectiveEnd(SymbolName);
7947 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007948 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007949 return false;
7950 }
7951
Jack Carter07c818d2013-01-25 01:31:34 +00007952 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007953 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7954 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007955 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007956 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7957 reportParseError("expected stack register");
7958 return false;
7959 }
7960
7961 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7962 if (!StackRegOpnd.isGPRAsmReg()) {
7963 reportParseError(StackRegOpnd.getStartLoc(),
7964 "expected general purpose register");
7965 return false;
7966 }
7967 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7968
7969 if (Parser.getTok().is(AsmToken::Comma))
7970 Parser.Lex();
7971 else {
7972 reportParseError("unexpected token, expected comma");
7973 return false;
7974 }
7975
7976 // Parse the frame size.
7977 const MCExpr *FrameSize;
7978 int64_t FrameSizeVal;
7979
7980 if (Parser.parseExpression(FrameSize)) {
7981 reportParseError("expected frame size value");
7982 return false;
7983 }
7984
Jim Grosbach13760bd2015-05-30 01:25:56 +00007985 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007986 reportParseError("frame size not an absolute expression");
7987 return false;
7988 }
7989
7990 if (Parser.getTok().is(AsmToken::Comma))
7991 Parser.Lex();
7992 else {
7993 reportParseError("unexpected token, expected comma");
7994 return false;
7995 }
7996
7997 // Parse the return register.
7998 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007999 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00008000 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
8001 reportParseError("expected return register");
8002 return false;
8003 }
8004
8005 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
8006 if (!ReturnRegOpnd.isGPRAsmReg()) {
8007 reportParseError(ReturnRegOpnd.getStartLoc(),
8008 "expected general purpose register");
8009 return false;
8010 }
8011
8012 // If this is not the end of the statement, report an error.
8013 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8014 reportParseError("unexpected token, expected end of statement");
8015 return false;
8016 }
8017
8018 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8019 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008020 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008021 return false;
8022 }
8023
Jack Carter07c818d2013-01-25 01:31:34 +00008024 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008025 parseDirectiveSet();
8026 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008027 }
8028
Daniel Sandersd97a6342014-08-13 10:07:34 +00008029 if (IDVal == ".mask" || IDVal == ".fmask") {
8030 // .mask bitmask, frame_offset
8031 // bitmask: One bit for each register used.
8032 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8033 // first register is expected to be saved.
8034 // Examples:
8035 // .mask 0x80000000, -4
8036 // .fmask 0x80000000, -4
8037 //
Jack Carterbe332172012-09-07 00:48:02 +00008038
Daniel Sandersd97a6342014-08-13 10:07:34 +00008039 // Parse the bitmask
8040 const MCExpr *BitMask;
8041 int64_t BitMaskVal;
8042
8043 if (Parser.parseExpression(BitMask)) {
8044 reportParseError("expected bitmask value");
8045 return false;
8046 }
8047
Jim Grosbach13760bd2015-05-30 01:25:56 +00008048 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008049 reportParseError("bitmask not an absolute expression");
8050 return false;
8051 }
8052
8053 if (Parser.getTok().is(AsmToken::Comma))
8054 Parser.Lex();
8055 else {
8056 reportParseError("unexpected token, expected comma");
8057 return false;
8058 }
8059
8060 // Parse the frame_offset
8061 const MCExpr *FrameOffset;
8062 int64_t FrameOffsetVal;
8063
8064 if (Parser.parseExpression(FrameOffset)) {
8065 reportParseError("expected frame offset value");
8066 return false;
8067 }
8068
Jim Grosbach13760bd2015-05-30 01:25:56 +00008069 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008070 reportParseError("frame offset not an absolute expression");
8071 return false;
8072 }
8073
8074 // If this is not the end of the statement, report an error.
8075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8076 reportParseError("unexpected token, expected end of statement");
8077 return false;
8078 }
8079
8080 if (IDVal == ".mask")
8081 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8082 else
8083 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008084 return false;
8085 }
8086
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008087 if (IDVal == ".nan")
8088 return parseDirectiveNaN();
8089
Jack Carter07c818d2013-01-25 01:31:34 +00008090 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008091 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008092 return false;
8093 }
8094
Rafael Espindolab59fb732014-03-28 18:50:26 +00008095 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008096 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008097 return false;
8098 }
8099
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008100 if (IDVal == ".dtprelword") {
8101 parseDirectiveDtpRelWord();
8102 return false;
8103 }
8104
8105 if (IDVal == ".dtpreldword") {
8106 parseDirectiveDtpRelDWord();
8107 return false;
8108 }
8109
8110 if (IDVal == ".tprelword") {
8111 parseDirectiveTpRelWord();
8112 return false;
8113 }
8114
8115 if (IDVal == ".tpreldword") {
8116 parseDirectiveTpRelDWord();
8117 return false;
8118 }
8119
Nirav Dave996fc132016-05-05 14:15:46 +00008120 if (IDVal == ".option") {
8121 parseDirectiveOption();
8122 return false;
8123 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008124
8125 if (IDVal == ".abicalls") {
8126 getTargetStreamer().emitDirectiveAbiCalls();
8127 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Fangrui Songf78650a2018-07-30 19:41:25 +00008128 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00008129 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008130 }
8131 return false;
8132 }
8133
Nirav Dave996fc132016-05-05 14:15:46 +00008134 if (IDVal == ".cpsetup") {
8135 parseDirectiveCPSetup();
8136 return false;
8137 }
8138 if (IDVal == ".cpreturn") {
8139 parseDirectiveCPReturn();
8140 return false;
8141 }
8142 if (IDVal == ".module") {
8143 parseDirectiveModule();
8144 return false;
8145 }
8146 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8147 parseInternalDirectiveReallowModule();
8148 return false;
8149 }
8150 if (IDVal == ".insn") {
8151 parseInsnDirective();
8152 return false;
8153 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008154 if (IDVal == ".rdata") {
8155 parseRSectionDirective(".rodata");
8156 return false;
8157 }
Nirav Dave996fc132016-05-05 14:15:46 +00008158 if (IDVal == ".sbss") {
8159 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8160 return false;
8161 }
8162 if (IDVal == ".sdata") {
8163 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8164 return false;
8165 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008166
Rafael Espindola870c4e92012-01-11 03:56:41 +00008167 return true;
8168}
8169
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008170bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8171 // If this is not the end of the statement, report an error.
8172 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8173 reportParseError("unexpected token, expected end of statement");
8174 return false;
8175 }
8176
8177 getTargetStreamer().reallowModuleDirective();
8178
8179 getParser().Lex(); // Eat EndOfStatement token.
8180 return false;
8181}
8182
Rafael Espindola870c4e92012-01-11 03:56:41 +00008183extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008184 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8185 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8186 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8187 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008188}
Jack Carterb4dbc172012-09-05 23:34:03 +00008189
8190#define GET_REGISTER_MATCHER
8191#define GET_MATCHER_IMPLEMENTATION
Simon Atanasyanc49da2e2018-09-13 08:38:03 +00008192#define GET_MNEMONIC_SPELL_CHECKER
Jack Carterb4dbc172012-09-05 23:34:03 +00008193#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008194
8195bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8196 // Find the appropriate table for this asm variant.
8197 const MatchEntry *Start, *End;
8198 switch (VariantID) {
8199 default: llvm_unreachable("invalid variant!");
8200 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8201 }
8202 // Search the table.
8203 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8204 return MnemonicRange.first != MnemonicRange.second;
8205}