blob: 8a8cf562abe7ef6d34da6e073b0f90ce380fc302 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000307 bool reportParseError(Twine ErrorMsg);
308 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000309
Jack Carterb5cf5902013-04-17 00:18:04 +0000310 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000311
312 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000313 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000314 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000315 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000316 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000317 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000318 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000319 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000320 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000321 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000322 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000323 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000324 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000325 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000326 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000327
328 bool parseSetAtDirective();
329 bool parseSetNoAtDirective();
330 bool parseSetMacroDirective();
331 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000332 bool parseSetMsaDirective();
333 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000334 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000335 bool parseSetReorderDirective();
336 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000337 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000338 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000339 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000340 bool parseSetOddSPRegDirective();
341 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000342 bool parseSetPopDirective();
343 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000344 bool parseSetSoftFloatDirective();
345 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000346
Jack Carterd76b2372013-03-21 21:44:16 +0000347 bool parseSetAssignment();
348
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000349 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000350 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000351 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000352 bool parseDirectiveDtpRelWord();
353 bool parseDirectiveDtpRelDWord();
354 bool parseDirectiveTpRelWord();
355 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000356 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000357 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000358 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
359 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000360
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000361 bool parseInternalDirectiveReallowModule();
362
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000363 bool eatComma(StringRef ErrorStr);
364
Jack Carter1ac53222013-02-20 23:11:17 +0000365 int matchCPURegisterName(StringRef Symbol);
366
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000367 int matchHWRegsRegisterName(StringRef Symbol);
368
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000369 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000370
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000371 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000372
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000373 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000374
Jack Carter5dc8ac92013-09-25 23:50:44 +0000375 int matchMSA128RegisterName(StringRef Name);
376
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000377 int matchMSA128CtrlRegisterName(StringRef Name);
378
Jack Carterd0bd6422013-04-18 00:41:53 +0000379 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000380
Toma Tabacu89a712b2015-04-15 10:48:56 +0000381 /// Returns the internal register number for the current AT. Also checks if
382 /// the current AT is unavailable (set to $0) and gives an error if it is.
383 /// This should be used in pseudo-instruction expansions which need AT.
384 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000385
Simon Dardis3aa8a902017-02-06 12:43:46 +0000386 bool canUseATReg();
387
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000388 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
389 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000390
391 // Helper function that checks if the value of a vector index is within the
392 // boundaries of accepted values for each RegisterKind
393 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
394 bool validateMSAIndex(int Val, int RegKind);
395
Daniel Sandersf0df2212014-08-04 12:20:00 +0000396 // Selects a new architecture by updating the FeatureBits with the necessary
397 // info including implied dependencies.
398 // Internally, it clears all the feature bits related to *any* architecture
399 // and selects the new one using the ToggleFeature functionality of the
400 // MCSubtargetInfo object that handles implied dependencies. The reason we
401 // clear all the arch related bits manually is because ToggleFeature only
402 // clears the features that imply the feature being cleared and not the
403 // features implied by the feature being cleared. This is easier to see
404 // with an example:
405 // --------------------------------------------------
406 // | Feature | Implies |
407 // | -------------------------------------------------|
408 // | FeatureMips1 | None |
409 // | FeatureMips2 | FeatureMips1 |
410 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
411 // | FeatureMips4 | FeatureMips3 |
412 // | ... | |
413 // --------------------------------------------------
414 //
415 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
416 // FeatureMipsGP64 | FeatureMips1)
417 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
418 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000419 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000420 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000421 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
422 STI.setFeatureBits(FeatureBits);
423 setAvailableFeatures(
424 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000425 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000426 }
427
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000428 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000429 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000430 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000431 setAvailableFeatures(
432 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000433 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000434 }
435 }
436
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000437 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000438 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000439 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000440 setAvailableFeatures(
441 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000442 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000443 }
444 }
445
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000446 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
447 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000448 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000449 }
450
451 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
452 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000453 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000454 }
455
Rafael Espindola870c4e92012-01-11 03:56:41 +0000456public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000457 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000458 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000459 Match_RequiresDifferentOperands,
460 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000461 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000462 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000463 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000464#define GET_OPERAND_DIAGNOSTIC_TYPES
465#include "MipsGenAsmMatcher.inc"
466#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000467 };
468
Akira Hatanakab11ef082015-11-14 06:35:56 +0000469 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000472 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
473 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000474 MCAsmParserExtension::Initialize(parser);
475
Toma Tabacu11e14a92015-04-21 11:50:52 +0000476 parser.addAliasForDirective(".asciiz", ".asciz");
477
Jack Carterb4dbc172012-09-05 23:34:03 +0000478 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000479 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000480
Toma Tabacu9db22db2014-09-09 10:15:38 +0000481 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000482 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000483 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000484
Toma Tabacu9db22db2014-09-09 10:15:38 +0000485 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000486 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000488
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000489 getTargetStreamer().updateABIInfo(*this);
490
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000491 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000492 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000493
494 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000495
Rafael Espindola699281c2016-05-18 11:58:50 +0000496 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000497
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000498 IsCpRestoreSet = false;
499 CpRestoreOffset = -1;
500
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000501 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000502 if ((TheTriple.getArch() == Triple::mips) ||
503 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000504 IsLittleEndian = false;
505 else
506 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000507 }
508
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000509 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
510 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
511
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000512 bool isGP64bit() const {
513 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
514 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000515
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 bool isFP64bit() const {
517 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
518 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000519
Eric Christophera5762812015-01-26 17:33:46 +0000520 const MipsABIInfo &getABI() const { return ABI; }
521 bool isABI_N32() const { return ABI.IsN32(); }
522 bool isABI_N64() const { return ABI.IsN64(); }
523 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 bool isABI_FPXX() const {
525 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
526 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000528 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000529 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000530 }
531
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 bool hasMips1() const {
537 return getSTI().getFeatureBits()[Mips::FeatureMips1];
538 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000539
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 bool hasMips2() const {
541 return getSTI().getFeatureBits()[Mips::FeatureMips2];
542 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000543
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 bool hasMips3() const {
545 return getSTI().getFeatureBits()[Mips::FeatureMips3];
546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 bool hasMips4() const {
549 return getSTI().getFeatureBits()[Mips::FeatureMips4];
550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 bool hasMips5() const {
553 return getSTI().getFeatureBits()[Mips::FeatureMips5];
554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000556 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000560 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000568 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000571
Daniel Sanders17793142015-02-18 16:24:50 +0000572 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000573 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Daniel Sanders17793142015-02-18 16:24:50 +0000576 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000577 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Daniel Sanders17793142015-02-18 16:24:50 +0000580 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000581 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Daniel Sanders17793142015-02-18 16:24:50 +0000584 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000585 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000588 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000589 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000591
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000592 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000593 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000594 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000595
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 bool hasDSP() const {
597 return getSTI().getFeatureBits()[Mips::FeatureDSP];
598 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000599
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 bool hasDSPR2() const {
601 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000603
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 bool hasDSPR3() const {
605 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
606 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000607
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000608 bool hasMSA() const {
609 return getSTI().getFeatureBits()[Mips::FeatureMSA];
610 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000611
Kai Nackee0245392015-01-27 19:11:28 +0000612 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000613 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000614 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000615
Daniel Sandersa6994442015-08-18 12:33:54 +0000616 bool inPicMode() {
617 return IsPicEnabled;
618 }
619
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000620 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000621 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000622 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000623
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000624 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000625 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000626 }
627
Eric Christophere8ae3e32015-05-07 23:10:21 +0000628 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000629 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000630 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000631
Toma Tabacud9d344b2015-04-27 14:05:04 +0000632 /// Warn if RegIndex is the same as the current AT.
633 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000634
635 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000636
637 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000638
639 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
640 AsmToken::TokenKind OperatorToken,
641 MCContext &Ctx) override {
642 switch(OperatorToken) {
643 default:
644 llvm_unreachable("Unknown token");
645 return nullptr;
646 case AsmToken::PercentCall16:
647 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
648 case AsmToken::PercentCall_Hi:
649 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
650 case AsmToken::PercentCall_Lo:
651 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
652 case AsmToken::PercentDtprel_Hi:
653 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
654 case AsmToken::PercentDtprel_Lo:
655 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
656 case AsmToken::PercentGot:
657 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
658 case AsmToken::PercentGot_Disp:
659 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
660 case AsmToken::PercentGot_Hi:
661 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
662 case AsmToken::PercentGot_Lo:
663 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
664 case AsmToken::PercentGot_Ofst:
665 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
666 case AsmToken::PercentGot_Page:
667 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
668 case AsmToken::PercentGottprel:
669 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
670 case AsmToken::PercentGp_Rel:
671 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
672 case AsmToken::PercentHi:
673 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
674 case AsmToken::PercentHigher:
675 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
676 case AsmToken::PercentHighest:
677 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
678 case AsmToken::PercentLo:
679 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
680 case AsmToken::PercentNeg:
681 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
682 case AsmToken::PercentPcrel_Hi:
683 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
684 case AsmToken::PercentPcrel_Lo:
685 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
686 case AsmToken::PercentTlsgd:
687 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
688 case AsmToken::PercentTlsldm:
689 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
690 case AsmToken::PercentTprel_Hi:
691 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
692 case AsmToken::PercentTprel_Lo:
693 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
694 }
695 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000696};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000697
698/// MipsOperand - Instances of this class represent a parsed Mips machine
699/// instruction.
700class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000701public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000702 /// Broad categories of register classes
703 /// The exact class is finalized by the render method.
704 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000705 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000706 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000707 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000708 RegKind_FCC = 4, /// FCC
709 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
710 RegKind_MSACtrl = 16, /// MSA control registers
711 RegKind_COP2 = 32, /// COP2
712 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
713 /// context).
714 RegKind_CCR = 128, /// CCR
715 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000716 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000717 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000718 /// Potentially any (e.g. $1)
719 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
720 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000721 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000722 };
723
724private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000725 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000726 k_Immediate, /// An immediate (possibly involving symbol references)
727 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000728 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000729 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000730 k_RegList, /// A physical register list
731 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000732 } Kind;
733
David Blaikie960ea3f2014-06-08 16:18:35 +0000734public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 MipsOperand(KindTy K, MipsAsmParser &Parser)
736 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
737
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000738 ~MipsOperand() override {
739 switch (Kind) {
740 case k_Immediate:
741 break;
742 case k_Memory:
743 delete Mem.Base;
744 break;
745 case k_RegList:
746 delete RegList.List;
747 case k_RegisterIndex:
748 case k_Token:
749 case k_RegPair:
750 break;
751 }
752 }
753
David Blaikie960ea3f2014-06-08 16:18:35 +0000754private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 /// For diagnostics, and checking the assembler temporary
756 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000757
Eric Christopher8996c5d2013-03-15 00:42:55 +0000758 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000759 const char *Data;
760 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000761 };
762
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000763 struct RegIdxOp {
764 unsigned Index; /// Index into the register class
765 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000766 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000768 };
769
770 struct ImmOp {
771 const MCExpr *Val;
772 };
773
774 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000776 const MCExpr *Off;
777 };
778
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000779 struct RegListOp {
780 SmallVector<unsigned, 10> *List;
781 };
782
Jack Carterb4dbc172012-09-05 23:34:03 +0000783 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000784 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000786 struct ImmOp Imm;
787 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000788 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000789 };
790
791 SMLoc StartLoc, EndLoc;
792
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000794 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
795 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000796 const MCRegisterInfo *RegInfo,
797 SMLoc S, SMLoc E,
798 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000799 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 Op->RegIdx.Index = Index;
801 Op->RegIdx.RegInfo = RegInfo;
802 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000803 Op->RegIdx.Tok.Data = Str.data();
804 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 Op->StartLoc = S;
806 Op->EndLoc = E;
807 return Op;
808 }
809
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000810public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 /// Coerce the register to GPR32 and return the real register for the current
812 /// target.
813 unsigned getGPR32Reg() const {
814 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000815 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 unsigned ClassID = Mips::GPR32RegClassID;
817 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000818 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000819
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000820 /// Coerce the register to GPR32 and return the real register for the current
821 /// target.
822 unsigned getGPRMM16Reg() const {
823 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
824 unsigned ClassID = Mips::GPR32RegClassID;
825 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
826 }
827
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 /// Coerce the register to GPR64 and return the real register for the current
829 /// target.
830 unsigned getGPR64Reg() const {
831 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
832 unsigned ClassID = Mips::GPR64RegClassID;
833 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000834 }
835
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836private:
837 /// Coerce the register to AFGR64 and return the real register for the current
838 /// target.
839 unsigned getAFGR64Reg() const {
840 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
841 if (RegIdx.Index % 2 != 0)
842 AsmParser.Warning(StartLoc, "Float register should be even.");
843 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
844 .getRegister(RegIdx.Index / 2);
845 }
846
847 /// Coerce the register to FGR64 and return the real register for the current
848 /// target.
849 unsigned getFGR64Reg() const {
850 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
851 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
852 .getRegister(RegIdx.Index);
853 }
854
855 /// Coerce the register to FGR32 and return the real register for the current
856 /// target.
857 unsigned getFGR32Reg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
859 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
860 .getRegister(RegIdx.Index);
861 }
862
863 /// Coerce the register to FGRH32 and return the real register for the current
864 /// target.
865 unsigned getFGRH32Reg() const {
866 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
867 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
868 .getRegister(RegIdx.Index);
869 }
870
871 /// Coerce the register to FCC and return the real register for the current
872 /// target.
873 unsigned getFCCReg() const {
874 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
875 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
876 .getRegister(RegIdx.Index);
877 }
878
879 /// Coerce the register to MSA128 and return the real register for the current
880 /// target.
881 unsigned getMSA128Reg() const {
882 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
883 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
884 // identical
885 unsigned ClassID = Mips::MSA128BRegClassID;
886 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
887 }
888
889 /// Coerce the register to MSACtrl and return the real register for the
890 /// current target.
891 unsigned getMSACtrlReg() const {
892 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
893 unsigned ClassID = Mips::MSACtrlRegClassID;
894 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
895 }
896
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000897 /// Coerce the register to COP0 and return the real register for the
898 /// current target.
899 unsigned getCOP0Reg() const {
900 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
901 unsigned ClassID = Mips::COP0RegClassID;
902 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
903 }
904
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 /// Coerce the register to COP2 and return the real register for the
906 /// current target.
907 unsigned getCOP2Reg() const {
908 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
909 unsigned ClassID = Mips::COP2RegClassID;
910 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
911 }
912
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000913 /// Coerce the register to COP3 and return the real register for the
914 /// current target.
915 unsigned getCOP3Reg() const {
916 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
917 unsigned ClassID = Mips::COP3RegClassID;
918 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
919 }
920
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 /// Coerce the register to ACC64DSP and return the real register for the
922 /// current target.
923 unsigned getACC64DSPReg() const {
924 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
925 unsigned ClassID = Mips::ACC64DSPRegClassID;
926 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
927 }
928
929 /// Coerce the register to HI32DSP and return the real register for the
930 /// current target.
931 unsigned getHI32DSPReg() const {
932 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
933 unsigned ClassID = Mips::HI32DSPRegClassID;
934 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
935 }
936
937 /// Coerce the register to LO32DSP and return the real register for the
938 /// current target.
939 unsigned getLO32DSPReg() const {
940 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
941 unsigned ClassID = Mips::LO32DSPRegClassID;
942 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
943 }
944
945 /// Coerce the register to CCR and return the real register for the
946 /// current target.
947 unsigned getCCRReg() const {
948 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
949 unsigned ClassID = Mips::CCRRegClassID;
950 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
951 }
952
953 /// Coerce the register to HWRegs and return the real register for the
954 /// current target.
955 unsigned getHWRegsReg() const {
956 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
957 unsigned ClassID = Mips::HWRegsRegClassID;
958 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
959 }
960
961public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000962 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000963 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000964 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000965 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000966 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000967 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000968 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000969 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000970 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000971
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000972 void addRegOperands(MCInst &Inst, unsigned N) const {
973 llvm_unreachable("Use a custom parser instead");
974 }
975
Daniel Sanders21bce302014-04-01 12:35:23 +0000976 /// Render the operand to an MCInst as a GPR32
977 /// Asserts if the wrong number of operands are requested, or the operand
978 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000979 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
980 assert(N == 1 && "Invalid number of operands!");
981 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
982 }
983
984 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
985 assert(N == 1 && "Invalid number of operands!");
986 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
987 }
988
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000989 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
990 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000991 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 }
993
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000994 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
995 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000996 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000997 }
998
Jozef Kolek1904fa22014-11-24 14:25:53 +0000999 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001001 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001002 }
1003
Zoran Jovanovic41688672015-02-10 16:36:20 +00001004 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001006 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001007 }
1008
Daniel Sanders21bce302014-04-01 12:35:23 +00001009 /// Render the operand to an MCInst as a GPR64
1010 /// Asserts if the wrong number of operands are requested, or the operand
1011 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1013 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001014 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 }
1016
1017 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1018 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001019 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 }
1021
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001022 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1023 assert(N == 1 && "Invalid number of operands!");
1024 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1025 }
1026
1027 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1028 assert(N == 1 && "Invalid number of operands!");
1029 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1030 }
1031
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1033 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001034 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 }
1036
1037 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1038 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001039 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001040 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001041 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001042 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001043 AsmParser.getParser().printError(
1044 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1045 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 }
1047
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001048 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1049 assert(N == 1 && "Invalid number of operands!");
1050 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1051 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1052 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1053 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1054 "registers");
1055 }
1056
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 }
1061
1062 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001064 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 }
1066
1067 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001069 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 }
1071
1072 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 }
1076
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001077 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1080 }
1081
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001082 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001084 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001085 }
1086
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001087 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001089 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001090 }
1091
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001094 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 }
1096
1097 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 }
1101
1102 void addLO32DSPAsmRegOperands(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(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 }
1106
1107 void addCCRAsmRegOperands(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(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 }
1111
1112 void addHWRegsAsmRegOperands(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(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 }
1116
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001117 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001118 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001120 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001121 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001122 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001123 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001124 Inst.addOperand(MCOperand::createImm(Imm));
1125 }
1126
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001127 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001128 void addSImmOperands(MCInst &Inst, unsigned N) const {
1129 if (isImm() && !isConstantImm()) {
1130 addExpr(Inst, getImm());
1131 return;
1132 }
1133 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1134 }
1135
1136 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001137 void addUImmOperands(MCInst &Inst, unsigned N) const {
1138 if (isImm() && !isConstantImm()) {
1139 addExpr(Inst, getImm());
1140 return;
1141 }
1142 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1143 }
1144
Daniel Sanders78e89022016-03-11 11:37:50 +00001145 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1146 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1147 assert(N == 1 && "Invalid number of operands!");
1148 int64_t Imm = getConstantImm() - Offset;
1149 Imm = SignExtend64<Bits>(Imm);
1150 Imm += Offset;
1151 Imm += AdjustOffset;
1152 Inst.addOperand(MCOperand::createImm(Imm));
1153 }
1154
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001155 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001156 assert(N == 1 && "Invalid number of operands!");
1157 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001158 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001159 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001160
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001161 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001162 assert(N == 2 && "Invalid number of operands!");
1163
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001164 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1165 ? getMemBase()->getGPR64Reg()
1166 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001167
1168 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001170 }
1171
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001172 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1173 assert(N == 2 && "Invalid number of operands!");
1174
Jim Grosbache9119e42015-05-13 18:37:00 +00001175 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001176
1177 const MCExpr *Expr = getMemOff();
1178 addExpr(Inst, Expr);
1179 }
1180
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001181 void addRegListOperands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
1183
1184 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001185 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001186 }
1187
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001188 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001190 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001191 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001192 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1193 Inst.addOperand(MCOperand::createReg(
1194 RegIdx.RegInfo->getRegClass(
1195 AsmParser.getABI().AreGprs64bit()
1196 ? Mips::GPR64RegClassID
1197 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1198 Inst.addOperand(MCOperand::createReg(
1199 RegIdx.RegInfo->getRegClass(
1200 AsmParser.getABI().AreGprs64bit()
1201 ? Mips::GPR64RegClassID
1202 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001203 }
1204
Zoran Jovanovic41688672015-02-10 16:36:20 +00001205 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 2 && "Invalid number of operands!");
1207 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001209 }
1210
Craig Topper56c590a2014-04-29 07:58:02 +00001211 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001212 // As a special case until we sort out the definition of div/divu, accept
1213 // $0/$zero here so that MCK_ZERO works correctly.
1214 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001216
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001217 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001218 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001219
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001220 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001221 int64_t Res;
1222 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001224
Daniel Sanders52da7af2015-11-06 12:11:03 +00001225 bool isConstantImmz() const {
1226 return isConstantImm() && getConstantImm() == 0;
1227 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001228
Daniel Sandersea4f6532015-11-06 12:22:31 +00001229 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1230 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1231 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001232
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001233 template <unsigned Bits> bool isSImm() const {
1234 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001237 template <unsigned Bits> bool isUImm() const {
1238 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1239 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001240
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001241 template <unsigned Bits> bool isAnyImm() const {
1242 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1243 isUInt<Bits>(getConstantImm()))
1244 : isImm();
1245 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001246
Daniel Sanders78e89022016-03-11 11:37:50 +00001247 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1248 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001249 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001250
Hrvoje Varga46458d02016-02-25 12:53:29 +00001251 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1252 return isConstantImm() && getConstantImm() >= Bottom &&
1253 getConstantImm() <= Top;
1254 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001255
Craig Topper56c590a2014-04-29 07:58:02 +00001256 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001257 // Note: It's not possible to pretend that other operand kinds are tokens.
1258 // The matcher emitter checks tokens first.
1259 return Kind == k_Token;
1260 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001261
Craig Topper56c590a2014-04-29 07:58:02 +00001262 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001263
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001264 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001265 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001266 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001267
Simon Dardis4ccda502016-05-27 13:56:36 +00001268 // Allow relocation operators.
1269 // FIXME: This predicate and others need to look through binary expressions
1270 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001271 template <unsigned Bits, unsigned ShiftAmount = 0>
1272 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001273 if (!isMem())
1274 return false;
1275 if (!getMemBase()->isGPRAsmReg())
1276 return false;
1277 if (isa<MCTargetExpr>(getMemOff()) ||
1278 (isConstantMemOff() &&
1279 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1280 return true;
1281 MCValue Res;
1282 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1283 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001284 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001285
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001286 bool isMemWithGRPMM16Base() const {
1287 return isMem() && getMemBase()->isMM16AsmReg();
1288 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001289
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001290 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1291 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1292 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1293 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001294
Jozef Kolek12c69822014-12-23 16:16:33 +00001295 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1296 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1297 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1298 && (getMemBase()->getGPR32Reg() == Mips::SP);
1299 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001300
Daniel Sanderse473dc92016-05-09 13:38:25 +00001301 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1302 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1303 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1304 && (getMemBase()->getGPR32Reg() == Mips::GP);
1305 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001306
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001307 template <unsigned Bits, unsigned ShiftLeftAmount>
1308 bool isScaledUImm() const {
1309 return isConstantImm() &&
1310 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001311 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001312
Daniel Sanders97297772016-03-22 14:40:00 +00001313 template <unsigned Bits, unsigned ShiftLeftAmount>
1314 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001315 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1316 return true;
1317 // Operand can also be a symbol or symbol plus offset in case of relocations.
1318 if (Kind != k_Immediate)
1319 return false;
1320 MCValue Res;
1321 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1322 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001323 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001324
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001325 bool isRegList16() const {
1326 if (!isRegList())
1327 return false;
1328
1329 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001330 if (Size < 2 || Size > 5)
1331 return false;
1332
1333 unsigned R0 = RegList.List->front();
1334 unsigned R1 = RegList.List->back();
1335 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1336 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001337 return false;
1338
1339 int PrevReg = *RegList.List->begin();
1340 for (int i = 1; i < Size - 1; i++) {
1341 int Reg = (*(RegList.List))[i];
1342 if ( Reg != PrevReg + 1)
1343 return false;
1344 PrevReg = Reg;
1345 }
1346
1347 return true;
1348 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001349
Vladimir Medic2b953d02013-10-01 09:48:56 +00001350 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001351
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001352 bool isLSAImm() const {
1353 if (!isConstantImm())
1354 return false;
1355 int64_t Val = getConstantImm();
1356 return 1 <= Val && Val <= 4;
1357 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001358
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001359 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001360
Zoran Jovanovic41688672015-02-10 16:36:20 +00001361 bool isMovePRegPair() const {
1362 if (Kind != k_RegList || RegList.List->size() != 2)
1363 return false;
1364
1365 unsigned R0 = RegList.List->front();
1366 unsigned R1 = RegList.List->back();
1367
1368 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1369 (R0 == Mips::A1 && R1 == Mips::A3) ||
1370 (R0 == Mips::A2 && R1 == Mips::A3) ||
1371 (R0 == Mips::A0 && R1 == Mips::S5) ||
1372 (R0 == Mips::A0 && R1 == Mips::S6) ||
1373 (R0 == Mips::A0 && R1 == Mips::A1) ||
1374 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001375 (R0 == Mips::A0 && R1 == Mips::A3) ||
1376 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1377 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1378 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1379 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1380 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1381 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1382 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1383 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001384 return true;
1385
1386 return false;
1387 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001388
1389 StringRef getToken() const {
1390 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001391 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001392 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001393
Zlatko Buljanba553a62016-05-09 08:07:28 +00001394 bool isRegPair() const {
1395 return Kind == k_RegPair && RegIdx.Index <= 30;
1396 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001397
Craig Topper56c590a2014-04-29 07:58:02 +00001398 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001399 // As a special case until we sort out the definition of div/divu, accept
1400 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001401 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1402 RegIdx.Kind & RegKind_GPR)
1403 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001404
Daniel Sanders976d9382016-07-05 13:38:40 +00001405 llvm_unreachable("Invalid access!");
1406 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001407 }
1408
Jack Carterb4dbc172012-09-05 23:34:03 +00001409 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001410 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001411 return Imm.Val;
1412 }
1413
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001414 int64_t getConstantImm() const {
1415 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001416 int64_t Value = 0;
1417 (void)Val->evaluateAsAbsolute(Value);
1418 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 }
1420
1421 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001422 assert((Kind == k_Memory) && "Invalid access!");
1423 return Mem.Base;
1424 }
1425
1426 const MCExpr *getMemOff() const {
1427 assert((Kind == k_Memory) && "Invalid access!");
1428 return Mem.Off;
1429 }
1430
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001431 int64_t getConstantMemOff() const {
1432 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1433 }
1434
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001435 const SmallVectorImpl<unsigned> &getRegList() const {
1436 assert((Kind == k_RegList) && "Invalid access!");
1437 return *(RegList.List);
1438 }
1439
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001440 unsigned getRegPair() const {
1441 assert((Kind == k_RegPair) && "Invalid access!");
1442 return RegIdx.Index;
1443 }
1444
David Blaikie960ea3f2014-06-08 16:18:35 +00001445 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1446 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001447 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001448 Op->Tok.Data = Str.data();
1449 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001450 Op->StartLoc = S;
1451 Op->EndLoc = S;
1452 return Op;
1453 }
1454
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001455 /// Create a numeric register (e.g. $1). The exact register remains
1456 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001457 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001458 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1459 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001460 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001461 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001462 }
1463
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001464 /// Create a register that is definitely a GPR.
1465 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001466 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001467 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1468 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1469 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001470 }
1471
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001472 /// Create a register that is definitely a FGR.
1473 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001474 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001475 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1476 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1477 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001478 }
1479
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001480 /// Create a register that is definitely a HWReg.
1481 /// This is typically only used for named registers such as $hwr_cpunum.
1482 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001483 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001484 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001485 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001486 }
1487
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001488 /// Create a register that is definitely an FCC.
1489 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001490 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001491 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1492 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1493 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001494 }
1495
1496 /// Create a register that is definitely an ACC.
1497 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001498 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001499 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1500 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1501 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001502 }
1503
1504 /// Create a register that is definitely an MSA128.
1505 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001506 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001507 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1508 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1509 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001510 }
1511
1512 /// Create a register that is definitely an MSACtrl.
1513 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001514 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001515 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1516 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1517 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001518 }
1519
David Blaikie960ea3f2014-06-08 16:18:35 +00001520 static std::unique_ptr<MipsOperand>
1521 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001522 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001523 Op->Imm.Val = Val;
1524 Op->StartLoc = S;
1525 Op->EndLoc = E;
1526 return Op;
1527 }
1528
David Blaikie960ea3f2014-06-08 16:18:35 +00001529 static std::unique_ptr<MipsOperand>
1530 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1531 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001532 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001533 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001534 Op->Mem.Off = Off;
1535 Op->StartLoc = S;
1536 Op->EndLoc = E;
1537 return Op;
1538 }
1539
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001540 static std::unique_ptr<MipsOperand>
1541 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1542 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001543 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001544
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001545 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001546 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001547 Op->StartLoc = StartLoc;
1548 Op->EndLoc = EndLoc;
1549 return Op;
1550 }
1551
Daniel Sandersd044e492016-05-09 13:10:57 +00001552 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1553 SMLoc S, SMLoc E,
1554 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001555 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001556 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001557 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1558 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001559 Op->StartLoc = S;
1560 Op->EndLoc = E;
1561 return Op;
1562 }
1563
Simon Dardis509da1a2017-02-13 16:06:48 +00001564 bool isGPRZeroAsmReg() const {
1565 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1566 }
1567
1568 bool isGPRNonZeroAsmReg() const {
1569 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1570 RegIdx.Index <= 31;
1571 }
1572
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001573 bool isGPRAsmReg() const {
1574 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001575 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001576
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001577 bool isMM16AsmReg() const {
1578 if (!(isRegIdx() && RegIdx.Kind))
1579 return false;
1580 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1581 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001582
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001583 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001584 bool isMM16AsmRegZero() const {
1585 if (!(isRegIdx() && RegIdx.Kind))
1586 return false;
1587 return (RegIdx.Index == 0 ||
1588 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1589 RegIdx.Index == 17);
1590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001591
Zoran Jovanovic41688672015-02-10 16:36:20 +00001592 bool isMM16AsmRegMoveP() const {
1593 if (!(isRegIdx() && RegIdx.Kind))
1594 return false;
1595 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1596 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001598
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001599 bool isFGRAsmReg() const {
1600 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1601 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001603
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001604 bool isStrictlyFGRAsmReg() const {
1605 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1606 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1607 }
1608
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001609 bool isHWRegsAsmReg() const {
1610 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001611 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001613 bool isCCRAsmReg() const {
1614 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001615 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001616
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001617 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001618 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1619 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001620 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001622
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001623 bool isACCAsmReg() const {
1624 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001626
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001627 bool isCOP0AsmReg() const {
1628 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 bool isCOP2AsmReg() const {
1632 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001633 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001634
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001635 bool isCOP3AsmReg() const {
1636 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1637 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001638
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001639 bool isMSA128AsmReg() const {
1640 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 bool isMSACtrlAsmReg() const {
1644 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001645 }
1646
Jack Carterb4dbc172012-09-05 23:34:03 +00001647 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001648 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001649 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001650 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001651
Craig Topper56c590a2014-04-29 07:58:02 +00001652 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 switch (Kind) {
1654 case k_Immediate:
1655 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001656 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001657 OS << ">";
1658 break;
1659 case k_Memory:
1660 OS << "Mem<";
1661 Mem.Base->print(OS);
1662 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001663 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001664 OS << ">";
1665 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001666 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001667 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1668 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 break;
1670 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001671 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001673 case k_RegList:
1674 OS << "RegList< ";
1675 for (auto Reg : (*RegList.List))
1676 OS << Reg << " ";
1677 OS << ">";
1678 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001679 case k_RegPair:
1680 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1681 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001682 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001683 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001684
1685 bool isValidForTie(const MipsOperand &Other) const {
1686 if (Kind != Other.Kind)
1687 return false;
1688
1689 switch (Kind) {
1690 default:
1691 llvm_unreachable("Unexpected kind");
1692 return false;
1693 case k_RegisterIndex: {
1694 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1695 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1696 return Token == OtherToken;
1697 }
1698 }
1699 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001700}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001701
1702} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001703
Jack Carter9e65aa32013-03-22 00:05:30 +00001704namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001705
Jack Carter9e65aa32013-03-22 00:05:30 +00001706extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001707
1708} // end namespace llvm
1709
Jack Carter9e65aa32013-03-22 00:05:30 +00001710static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1711 return MipsInsts[Opcode];
1712}
1713
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001714static bool hasShortDelaySlot(unsigned Opcode) {
1715 switch (Opcode) {
1716 case Mips::JALS_MM:
1717 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001718 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001719 case Mips::BGEZALS_MM:
1720 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001721 return true;
1722 default:
1723 return false;
1724 }
1725}
1726
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001727static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1728 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1729 return &SRExpr->getSymbol();
1730 }
1731
1732 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1733 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1734 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1735
1736 if (LHSSym)
1737 return LHSSym;
1738
1739 if (RHSSym)
1740 return RHSSym;
1741
1742 return nullptr;
1743 }
1744
1745 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1746 return getSingleMCSymbol(UExpr->getSubExpr());
1747
1748 return nullptr;
1749}
1750
1751static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1752 if (isa<MCSymbolRefExpr>(Expr))
1753 return 1;
1754
1755 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1756 return countMCSymbolRefExpr(BExpr->getLHS()) +
1757 countMCSymbolRefExpr(BExpr->getRHS());
1758
1759 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1760 return countMCSymbolRefExpr(UExpr->getSubExpr());
1761
1762 return 0;
1763}
1764
Jack Carter9e65aa32013-03-22 00:05:30 +00001765bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001766 MCStreamer &Out,
1767 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001768 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001769 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001770 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001771
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001773
1774 if (MCID.isBranch() || MCID.isCall()) {
1775 const unsigned Opcode = Inst.getOpcode();
1776 MCOperand Offset;
1777
1778 switch (Opcode) {
1779 default:
1780 break;
Kai Nackee0245392015-01-27 19:11:28 +00001781 case Mips::BBIT0:
1782 case Mips::BBIT032:
1783 case Mips::BBIT1:
1784 case Mips::BBIT132:
1785 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001786 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001787
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001788 case Mips::BEQ:
1789 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001790 case Mips::BEQ_MM:
1791 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001792 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001793 Offset = Inst.getOperand(2);
1794 if (!Offset.isImm())
1795 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001796 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001797 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001798 if (OffsetToAlignment(Offset.getImm(),
1799 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001800 return Error(IDLoc, "branch to misaligned address");
1801 break;
1802 case Mips::BGEZ:
1803 case Mips::BGTZ:
1804 case Mips::BLEZ:
1805 case Mips::BLTZ:
1806 case Mips::BGEZAL:
1807 case Mips::BLTZAL:
1808 case Mips::BC1F:
1809 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001810 case Mips::BGEZ_MM:
1811 case Mips::BGTZ_MM:
1812 case Mips::BLEZ_MM:
1813 case Mips::BLTZ_MM:
1814 case Mips::BGEZAL_MM:
1815 case Mips::BLTZAL_MM:
1816 case Mips::BC1F_MM:
1817 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001818 case Mips::BC1EQZC_MMR6:
1819 case Mips::BC1NEZC_MMR6:
1820 case Mips::BC2EQZC_MMR6:
1821 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001822 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001823 Offset = Inst.getOperand(1);
1824 if (!Offset.isImm())
1825 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001826 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001827 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001828 if (OffsetToAlignment(Offset.getImm(),
1829 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001830 return Error(IDLoc, "branch to misaligned address");
1831 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001832 case Mips::BGEC: case Mips::BGEC_MMR6:
1833 case Mips::BLTC: case Mips::BLTC_MMR6:
1834 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1835 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1836 case Mips::BEQC: case Mips::BEQC_MMR6:
1837 case Mips::BNEC: case Mips::BNEC_MMR6:
1838 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1839 Offset = Inst.getOperand(2);
1840 if (!Offset.isImm())
1841 break; // We'll deal with this situation later on when applying fixups.
1842 if (!isIntN(18, Offset.getImm()))
1843 return Error(IDLoc, "branch target out of range");
1844 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1845 return Error(IDLoc, "branch to misaligned address");
1846 break;
1847 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1848 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1849 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1850 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1851 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1852 Offset = Inst.getOperand(1);
1853 if (!Offset.isImm())
1854 break; // We'll deal with this situation later on when applying fixups.
1855 if (!isIntN(18, Offset.getImm()))
1856 return Error(IDLoc, "branch target out of range");
1857 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1858 return Error(IDLoc, "branch to misaligned address");
1859 break;
1860 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1861 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1862 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1863 Offset = Inst.getOperand(1);
1864 if (!Offset.isImm())
1865 break; // We'll deal with this situation later on when applying fixups.
1866 if (!isIntN(23, Offset.getImm()))
1867 return Error(IDLoc, "branch target out of range");
1868 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1869 return Error(IDLoc, "branch to misaligned address");
1870 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001871 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001872 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001873 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001874 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001875 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1876 Offset = Inst.getOperand(1);
1877 if (!Offset.isImm())
1878 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001879 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001880 return Error(IDLoc, "branch target out of range");
1881 if (OffsetToAlignment(Offset.getImm(), 2LL))
1882 return Error(IDLoc, "branch to misaligned address");
1883 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001884 }
1885 }
1886
Daniel Sandersa84989a2014-06-16 13:25:35 +00001887 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1888 // We still accept it but it is a normal nop.
1889 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1890 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1891 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1892 "nop instruction");
1893 }
1894
Kai Nackee0245392015-01-27 19:11:28 +00001895 if (hasCnMips()) {
1896 const unsigned Opcode = Inst.getOpcode();
1897 MCOperand Opnd;
1898 int Imm;
1899
1900 switch (Opcode) {
1901 default:
1902 break;
1903
1904 case Mips::BBIT0:
1905 case Mips::BBIT032:
1906 case Mips::BBIT1:
1907 case Mips::BBIT132:
1908 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1909 // The offset is handled above
1910 Opnd = Inst.getOperand(1);
1911 if (!Opnd.isImm())
1912 return Error(IDLoc, "expected immediate operand kind");
1913 Imm = Opnd.getImm();
1914 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1915 Opcode == Mips::BBIT1 ? 63 : 31))
1916 return Error(IDLoc, "immediate operand value out of range");
1917 if (Imm > 31) {
1918 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1919 : Mips::BBIT132);
1920 Inst.getOperand(1).setImm(Imm - 32);
1921 }
1922 break;
1923
Kai Nackee0245392015-01-27 19:11:28 +00001924 case Mips::SEQi:
1925 case Mips::SNEi:
1926 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1927 Opnd = Inst.getOperand(2);
1928 if (!Opnd.isImm())
1929 return Error(IDLoc, "expected immediate operand kind");
1930 Imm = Opnd.getImm();
1931 if (!isInt<10>(Imm))
1932 return Error(IDLoc, "immediate operand value out of range");
1933 break;
1934 }
1935 }
1936
Simon Dardis509da1a2017-02-13 16:06:48 +00001937 // Warn on division by zero. We're checking here as all instructions get
1938 // processed here, not just the macros that need expansion.
1939 //
1940 // The MIPS backend models most of the divison instructions and macros as
1941 // three operand instructions. The pre-R6 divide instructions however have
1942 // two operands and explicitly define HI/LO as part of the instruction,
1943 // not in the operands.
1944 unsigned FirstOp = 1;
1945 unsigned SecondOp = 2;
1946 switch (Inst.getOpcode()) {
1947 default:
1948 break;
1949 case Mips::SDivIMacro:
1950 case Mips::UDivIMacro:
1951 case Mips::DSDivIMacro:
1952 case Mips::DUDivIMacro:
1953 if (Inst.getOperand(2).getImm() == 0) {
1954 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1955 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1956 Warning(IDLoc, "dividing zero by zero");
1957 else
1958 Warning(IDLoc, "division by zero");
1959 }
1960 break;
1961 case Mips::DSDIV:
1962 case Mips::SDIV:
1963 case Mips::UDIV:
1964 case Mips::DUDIV:
1965 case Mips::UDIV_MM:
1966 case Mips::SDIV_MM:
1967 FirstOp = 0;
1968 SecondOp = 1;
1969 case Mips::SDivMacro:
1970 case Mips::DSDivMacro:
1971 case Mips::UDivMacro:
1972 case Mips::DUDivMacro:
1973 case Mips::DIV:
1974 case Mips::DIVU:
1975 case Mips::DDIV:
1976 case Mips::DDIVU:
1977 case Mips::DIVU_MMR6:
1978 case Mips::DDIVU_MM64R6:
1979 case Mips::DIV_MMR6:
1980 case Mips::DDIV_MM64R6:
1981 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1982 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1983 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1984 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1985 Warning(IDLoc, "dividing zero by zero");
1986 else
1987 Warning(IDLoc, "division by zero");
1988 }
1989 break;
1990 }
1991
Simon Atanasyan50485142016-12-12 17:40:26 +00001992 // For PIC code convert unconditional jump to unconditional branch.
1993 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1994 inPicMode()) {
1995 MCInst BInst;
1996 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1997 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1998 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1999 BInst.addOperand(Inst.getOperand(0));
2000 Inst = BInst;
2001 }
2002
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002003 // This expansion is not in a function called by tryExpandInstruction()
2004 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002005 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2006 inPicMode()) {
2007 warnIfNoMacro(IDLoc);
2008
2009 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2010
2011 // We can do this expansion if there's only 1 symbol in the argument
2012 // expression.
2013 if (countMCSymbolRefExpr(JalExpr) > 1)
2014 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2015
2016 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002017 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002018 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2019
2020 // FIXME: Add support for label+offset operands (currently causes an error).
2021 // FIXME: Add support for forward-declared local symbols.
2022 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002023 if (JalSym->isInSection() || JalSym->isTemporary() ||
2024 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002025 if (isABI_O32()) {
2026 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002027 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002028 // R_(MICRO)MIPS_GOT16 label
2029 // addiu $25, $25, 0
2030 // R_(MICRO)MIPS_LO16 label
2031 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002032 const MCExpr *Got16RelocExpr =
2033 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2034 const MCExpr *Lo16RelocExpr =
2035 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002036
Daniel Sandersa736b372016-04-29 13:33:12 +00002037 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2038 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2039 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2040 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002041 } else if (isABI_N32() || isABI_N64()) {
2042 // If it's a local symbol and the N32/N64 ABIs are being used,
2043 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002044 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002045 // R_(MICRO)MIPS_GOT_DISP label
2046 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002047 const MCExpr *GotDispRelocExpr =
2048 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002049
Daniel Sandersa736b372016-04-29 13:33:12 +00002050 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2051 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2052 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002053 }
2054 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002055 // If it's an external/weak symbol, we expand to:
2056 // lw/ld $25, 0($gp)
2057 // R_(MICRO)MIPS_CALL16 label
2058 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002059 const MCExpr *Call16RelocExpr =
2060 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002061
Daniel Sandersa736b372016-04-29 13:33:12 +00002062 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2063 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002064 }
2065
2066 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002067 if (IsCpRestoreSet && inMicroMipsMode())
2068 JalrInst.setOpcode(Mips::JALRS_MM);
2069 else
2070 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002071 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2072 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2073
2074 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2075 // This relocation is supposed to be an optimization hint for the linker
2076 // and is not necessary for correctness.
2077
2078 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002079 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002080 }
2081
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002082 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2083 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002084 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002085 // reference or immediate we may have to expand instructions.
2086 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002087 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002088 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2089 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002090 MCOperand &Op = Inst.getOperand(i);
2091 if (Op.isImm()) {
2092 int MemOffset = Op.getImm();
2093 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002094 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002095 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002096 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002097 }
2098 } else if (Op.isExpr()) {
2099 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002100 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002101 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002102 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002103 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002105 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002106 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002107 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002108 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002109 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002110 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002111 }
2112 }
2113 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002115 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002116
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002117 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002118 if (MCID.mayLoad()) {
2119 // Try to create 16-bit GP relative load instruction.
2120 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2121 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2122 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2123 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2124 MCOperand &Op = Inst.getOperand(i);
2125 if (Op.isImm()) {
2126 int MemOffset = Op.getImm();
2127 MCOperand &DstReg = Inst.getOperand(0);
2128 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002129 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002130 getContext().getRegisterInfo()->getRegClass(
2131 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002132 (BaseReg.getReg() == Mips::GP ||
2133 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002134
Daniel Sandersa736b372016-04-29 13:33:12 +00002135 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2136 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002137 return false;
2138 }
2139 }
2140 }
2141 } // for
2142 } // if load
2143
2144 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2145
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002146 MCOperand Opnd;
2147 int Imm;
2148
2149 switch (Inst.getOpcode()) {
2150 default:
2151 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002152 case Mips::ADDIUSP_MM:
2153 Opnd = Inst.getOperand(0);
2154 if (!Opnd.isImm())
2155 return Error(IDLoc, "expected immediate operand kind");
2156 Imm = Opnd.getImm();
2157 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2158 Imm % 4 != 0)
2159 return Error(IDLoc, "immediate operand value out of range");
2160 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002161 case Mips::SLL16_MM:
2162 case Mips::SRL16_MM:
2163 Opnd = Inst.getOperand(2);
2164 if (!Opnd.isImm())
2165 return Error(IDLoc, "expected immediate operand kind");
2166 Imm = Opnd.getImm();
2167 if (Imm < 1 || Imm > 8)
2168 return Error(IDLoc, "immediate operand value out of range");
2169 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002170 case Mips::LI16_MM:
2171 Opnd = Inst.getOperand(1);
2172 if (!Opnd.isImm())
2173 return Error(IDLoc, "expected immediate operand kind");
2174 Imm = Opnd.getImm();
2175 if (Imm < -1 || Imm > 126)
2176 return Error(IDLoc, "immediate operand value out of range");
2177 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002178 case Mips::ADDIUR2_MM:
2179 Opnd = Inst.getOperand(2);
2180 if (!Opnd.isImm())
2181 return Error(IDLoc, "expected immediate operand kind");
2182 Imm = Opnd.getImm();
2183 if (!(Imm == 1 || Imm == -1 ||
2184 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2185 return Error(IDLoc, "immediate operand value out of range");
2186 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002187 case Mips::ANDI16_MM:
2188 Opnd = Inst.getOperand(2);
2189 if (!Opnd.isImm())
2190 return Error(IDLoc, "expected immediate operand kind");
2191 Imm = Opnd.getImm();
2192 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2193 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2194 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2195 return Error(IDLoc, "immediate operand value out of range");
2196 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002197 case Mips::LBU16_MM:
2198 Opnd = Inst.getOperand(2);
2199 if (!Opnd.isImm())
2200 return Error(IDLoc, "expected immediate operand kind");
2201 Imm = Opnd.getImm();
2202 if (Imm < -1 || Imm > 14)
2203 return Error(IDLoc, "immediate operand value out of range");
2204 break;
2205 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002206 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002207 Opnd = Inst.getOperand(2);
2208 if (!Opnd.isImm())
2209 return Error(IDLoc, "expected immediate operand kind");
2210 Imm = Opnd.getImm();
2211 if (Imm < 0 || Imm > 15)
2212 return Error(IDLoc, "immediate operand value out of range");
2213 break;
2214 case Mips::LHU16_MM:
2215 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002216 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002217 Opnd = Inst.getOperand(2);
2218 if (!Opnd.isImm())
2219 return Error(IDLoc, "expected immediate operand kind");
2220 Imm = Opnd.getImm();
2221 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2222 return Error(IDLoc, "immediate operand value out of range");
2223 break;
2224 case Mips::LW16_MM:
2225 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002226 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002227 Opnd = Inst.getOperand(2);
2228 if (!Opnd.isImm())
2229 return Error(IDLoc, "expected immediate operand kind");
2230 Imm = Opnd.getImm();
2231 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2232 return Error(IDLoc, "immediate operand value out of range");
2233 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002234 case Mips::ADDIUPC_MM:
2235 MCOperand Opnd = Inst.getOperand(1);
2236 if (!Opnd.isImm())
2237 return Error(IDLoc, "expected immediate operand kind");
2238 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002239 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002240 return Error(IDLoc, "immediate operand value out of range");
2241 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002242 }
2243 }
2244
Daniel Sandersd8c07762016-04-18 12:35:36 +00002245 bool FillDelaySlot =
2246 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2247 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002248 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002249
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002250 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002251 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002252 switch (ExpandResult) {
2253 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002254 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002255 break;
2256 case MER_Success:
2257 break;
2258 case MER_Fail:
2259 return true;
2260 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002261
Daniel Sanderscda908a2016-05-16 09:10:13 +00002262 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2263 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2264 if (inMicroMipsMode())
2265 TOut.setUsesMicroMips();
2266
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002267 // If this instruction has a delay slot and .set reorder is active,
2268 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002269 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002270 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2271 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002272 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002273
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002274 if ((Inst.getOpcode() == Mips::JalOneReg ||
2275 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2276 isPicAndNotNxxAbi()) {
2277 if (IsCpRestoreSet) {
2278 // We need a NOP between the JALR and the LW:
2279 // If .set reorder has been used, we've already emitted a NOP.
2280 // If .set noreorder has been used, we need to emit a NOP at this point.
2281 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002282 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2283 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002284
2285 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002286 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002287 } else
2288 Warning(IDLoc, "no .cprestore used in PIC mode");
2289 }
2290
Jack Carter9e65aa32013-03-22 00:05:30 +00002291 return false;
2292}
2293
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002294MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002295MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2296 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002297 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002298 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002299 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002300 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002301 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002302 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002303 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002304 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002305 case Mips::LoadAddrImm64:
2306 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2307 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2308 "expected immediate operand kind");
2309
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002310 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2311 Inst.getOperand(1),
2312 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002313 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002314 ? MER_Fail
2315 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002316 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002317 case Mips::LoadAddrReg64:
2318 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2319 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2320 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2321 "expected immediate operand kind");
2322
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002323 return expandLoadAddress(Inst.getOperand(0).getReg(),
2324 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2325 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002326 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002327 ? MER_Fail
2328 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002329 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002330 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002331 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2332 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002333 case Mips::SWM_MM:
2334 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002335 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2336 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002337 case Mips::JalOneReg:
2338 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002339 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002340 case Mips::BneImm:
2341 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002342 case Mips::BEQLImmMacro:
2343 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002344 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002345 case Mips::BLT:
2346 case Mips::BLE:
2347 case Mips::BGE:
2348 case Mips::BGT:
2349 case Mips::BLTU:
2350 case Mips::BLEU:
2351 case Mips::BGEU:
2352 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002353 case Mips::BLTL:
2354 case Mips::BLEL:
2355 case Mips::BGEL:
2356 case Mips::BGTL:
2357 case Mips::BLTUL:
2358 case Mips::BLEUL:
2359 case Mips::BGEUL:
2360 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002361 case Mips::BLTImmMacro:
2362 case Mips::BLEImmMacro:
2363 case Mips::BGEImmMacro:
2364 case Mips::BGTImmMacro:
2365 case Mips::BLTUImmMacro:
2366 case Mips::BLEUImmMacro:
2367 case Mips::BGEUImmMacro:
2368 case Mips::BGTUImmMacro:
2369 case Mips::BLTLImmMacro:
2370 case Mips::BLELImmMacro:
2371 case Mips::BGELImmMacro:
2372 case Mips::BGTLImmMacro:
2373 case Mips::BLTULImmMacro:
2374 case Mips::BLEULImmMacro:
2375 case Mips::BGEULImmMacro:
2376 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002377 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002378 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002379 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002380 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2381 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002382 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002383 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002384 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2385 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002386 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002387 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002388 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2389 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002390 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002391 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002392 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2393 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002394 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002395 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2396 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002397 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002398 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002399 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002400 case Mips::PseudoTRUNC_W_D:
2401 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2402 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002403
2404 case Mips::LoadImmSingleGPR:
2405 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2406 ? MER_Fail
2407 : MER_Success;
2408 case Mips::LoadImmSingleFGR:
2409 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2410 ? MER_Fail
2411 : MER_Success;
2412 case Mips::LoadImmDoubleGPR:
2413 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2414 ? MER_Fail
2415 : MER_Success;
2416 case Mips::LoadImmDoubleFGR:
2417 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2418 ? MER_Fail
2419 : MER_Success;
2420 case Mips::LoadImmDoubleFGR_32:
2421 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2422 ? MER_Fail
2423 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002424 case Mips::Ulh:
2425 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2426 case Mips::Ulhu:
2427 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002428 case Mips::Ush:
2429 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002430 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002431 case Mips::Usw:
2432 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002433 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002434 case Mips::NORImm64:
2435 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2436 case Mips::SLTImm64:
2437 if (isInt<16>(Inst.getOperand(2).getImm())) {
2438 Inst.setOpcode(Mips::SLTi64);
2439 return MER_NotAMacro;
2440 }
2441 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2442 case Mips::SLTUImm64:
2443 if (isInt<16>(Inst.getOperand(2).getImm())) {
2444 Inst.setOpcode(Mips::SLTiu64);
2445 return MER_NotAMacro;
2446 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002447 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002448 case Mips::ADDi: case Mips::ADDi_MM:
2449 case Mips::ADDiu: case Mips::ADDiu_MM:
2450 case Mips::SLTi: case Mips::SLTi_MM:
2451 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002452 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2453 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2454 int64_t ImmValue = Inst.getOperand(2).getImm();
2455 if (isInt<16>(ImmValue))
2456 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002457 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2458 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002459 }
2460 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002461 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2462 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2463 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002464 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2465 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2466 int64_t ImmValue = Inst.getOperand(2).getImm();
2467 if (isUInt<16>(ImmValue))
2468 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002469 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2470 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002471 }
2472 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002473 case Mips::ROL:
2474 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002475 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002476 case Mips::ROLImm:
2477 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002478 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002479 case Mips::DROL:
2480 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002481 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002482 case Mips::DROLImm:
2483 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002484 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002485 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002486 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002487 case Mips::MULImmMacro:
2488 case Mips::DMULImmMacro:
2489 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2490 case Mips::MULOMacro:
2491 case Mips::DMULOMacro:
2492 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2493 case Mips::MULOUMacro:
2494 case Mips::DMULOUMacro:
2495 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2496 case Mips::DMULMacro:
2497 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002498 case Mips::LDMacro:
2499 case Mips::SDMacro:
2500 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2501 Inst.getOpcode() == Mips::LDMacro)
2502 ? MER_Fail
2503 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002504 case Mips::SEQMacro:
2505 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2506 case Mips::SEQIMacro:
2507 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002508 }
Jack Carter30a59822012-10-04 04:03:53 +00002509}
Jack Carter92995f12012-10-06 00:53:28 +00002510
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002511bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002512 MCStreamer &Out,
2513 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002514 MipsTargetStreamer &TOut = getTargetStreamer();
2515
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002516 // Create a JALR instruction which is going to replace the pseudo-JAL.
2517 MCInst JalrInst;
2518 JalrInst.setLoc(IDLoc);
2519 const MCOperand FirstRegOp = Inst.getOperand(0);
2520 const unsigned Opcode = Inst.getOpcode();
2521
2522 if (Opcode == Mips::JalOneReg) {
2523 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002524 if (IsCpRestoreSet && inMicroMipsMode()) {
2525 JalrInst.setOpcode(Mips::JALRS16_MM);
2526 JalrInst.addOperand(FirstRegOp);
2527 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002528 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002529 JalrInst.addOperand(FirstRegOp);
2530 } else {
2531 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002532 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002533 JalrInst.addOperand(FirstRegOp);
2534 }
2535 } else if (Opcode == Mips::JalTwoReg) {
2536 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002537 if (IsCpRestoreSet && inMicroMipsMode())
2538 JalrInst.setOpcode(Mips::JALRS_MM);
2539 else
2540 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002541 JalrInst.addOperand(FirstRegOp);
2542 const MCOperand SecondRegOp = Inst.getOperand(1);
2543 JalrInst.addOperand(SecondRegOp);
2544 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002545 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002546
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002547 // If .set reorder is active and branch instruction has a delay slot,
2548 // emit a NOP after it.
2549 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002550 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2551 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2552 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002553
2554 return false;
2555}
2556
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002557/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002558template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002559 unsigned BitNum = findFirstSet(x);
2560
2561 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2562}
2563
2564/// Load (or add) an immediate into a register.
2565///
2566/// @param ImmValue The immediate to load.
2567/// @param DstReg The register that will hold the immediate.
2568/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2569/// for a simple initialization.
2570/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2571/// @param IsAddress True if the immediate represents an address. False if it
2572/// is an integer.
2573/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002574bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002575 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002576 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2577 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002578 MipsTargetStreamer &TOut = getTargetStreamer();
2579
Toma Tabacu00e98672015-05-01 12:19:27 +00002580 if (!Is32BitImm && !isGP64bit()) {
2581 Error(IDLoc, "instruction requires a 64-bit architecture");
2582 return true;
2583 }
2584
Daniel Sanders03f9c012015-07-14 12:24:22 +00002585 if (Is32BitImm) {
2586 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2587 // Sign extend up to 64-bit so that the predicates match the hardware
2588 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2589 // true.
2590 ImmValue = SignExtend64<32>(ImmValue);
2591 } else {
2592 Error(IDLoc, "instruction requires a 32-bit immediate");
2593 return true;
2594 }
2595 }
2596
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002597 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2598 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2599
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002600 bool UseSrcReg = false;
2601 if (SrcReg != Mips::NoRegister)
2602 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002603
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002604 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002605 if (UseSrcReg &&
2606 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002607 // At this point we need AT to perform the expansions and we exit if it is
2608 // not available.
2609 unsigned ATReg = getATReg(IDLoc);
2610 if (!ATReg)
2611 return true;
2612 TmpReg = ATReg;
2613 }
2614
Daniel Sanders03f9c012015-07-14 12:24:22 +00002615 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002616 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002617 SrcReg = ZeroReg;
2618
2619 // This doesn't quite follow the usual ABI expectations for N32 but matches
2620 // traditional assembler behaviour. N32 would normally use addiu for both
2621 // integers and addresses.
2622 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002623 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002624 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002625 }
2626
Daniel Sandersa736b372016-04-29 13:33:12 +00002627 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002628 return false;
2629 }
2630
2631 if (isUInt<16>(ImmValue)) {
2632 unsigned TmpReg = DstReg;
2633 if (SrcReg == DstReg) {
2634 TmpReg = getATReg(IDLoc);
2635 if (!TmpReg)
2636 return true;
2637 }
2638
Daniel Sandersa736b372016-04-29 13:33:12 +00002639 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002640 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002641 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002642 return false;
2643 }
2644
2645 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002646 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002647
Toma Tabacu79588102015-04-29 10:19:56 +00002648 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2649 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002650 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002651 // Traditional behaviour seems to special case this particular value. It's
2652 // not clear why other masks are handled differently.
2653 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002654 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2655 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002656 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002657 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002658 return false;
2659 }
2660
2661 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002662 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002663 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2664 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002665 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002666 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002667 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002668 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002669 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002670 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002671
Daniel Sandersa736b372016-04-29 13:33:12 +00002672 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002673 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002674 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002675 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002676 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002677 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002678 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002679
2680 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2681 if (Is32BitImm) {
2682 Error(IDLoc, "instruction requires a 32-bit immediate");
2683 return true;
2684 }
2685
2686 // Traditionally, these immediates are shifted as little as possible and as
2687 // such we align the most significant bit to bit 15 of our temporary.
2688 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2689 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2690 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2691 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002692 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2693 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002694
2695 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002696 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002697
2698 return false;
2699 }
2700
2701 warnIfNoMacro(IDLoc);
2702
2703 // The remaining case is packed with a sequence of dsll and ori with zeros
2704 // being omitted and any neighbouring dsll's being coalesced.
2705 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2706
2707 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2708 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002709 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002710 return false;
2711
2712 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2713 // skip it and defer the shift to the next chunk.
2714 unsigned ShiftCarriedForwards = 16;
2715 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2716 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2717
2718 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002719 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2720 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002721 ShiftCarriedForwards = 0;
2722 }
2723
2724 ShiftCarriedForwards += 16;
2725 }
2726 ShiftCarriedForwards -= 16;
2727
2728 // Finish any remaining shifts left by trailing zeros.
2729 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002730 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002731
2732 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002733 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002734
Matheus Almeida3813d572014-06-19 14:39:14 +00002735 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002736}
Jack Carter92995f12012-10-06 00:53:28 +00002737
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002738bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002739 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002740 const MCOperand &ImmOp = Inst.getOperand(1);
2741 assert(ImmOp.isImm() && "expected immediate operand kind");
2742 const MCOperand &DstRegOp = Inst.getOperand(0);
2743 assert(DstRegOp.isReg() && "expected register operand kind");
2744
2745 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002746 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002747 return true;
2748
2749 return false;
2750}
2751
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002752bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2753 const MCOperand &Offset,
2754 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002755 MCStreamer &Out,
2756 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002757 // la can't produce a usable address when addresses are 64-bit.
2758 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2759 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2760 // We currently can't do this because we depend on the equality
2761 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2762 Error(IDLoc, "la used to load 64-bit address");
2763 // Continue as if we had 'dla' instead.
2764 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002765 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002766 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002767
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002768 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002769 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002770 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002771 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002772 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002773
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002774 if (!Offset.isImm())
2775 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002776 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002777
Scott Egerton24557012016-01-21 15:11:01 +00002778 if (!ABI.ArePtrs64bit()) {
2779 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2780 Is32BitAddress = true;
2781 }
2782
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002783 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002784 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002785}
2786
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002787bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2788 unsigned DstReg, unsigned SrcReg,
2789 bool Is32BitSym, SMLoc IDLoc,
2790 MCStreamer &Out,
2791 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002792 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002793 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002794 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002795
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002796 if (inPicMode() && ABI.IsO32()) {
2797 MCValue Res;
2798 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2799 Error(IDLoc, "expected relocatable expression");
2800 return true;
2801 }
2802 if (Res.getSymB() != nullptr) {
2803 Error(IDLoc, "expected relocatable expression with only one symbol");
2804 return true;
2805 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002806
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002807 // The case where the result register is $25 is somewhat special. If the
2808 // symbol in the final relocation is external and not modified with a
2809 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2810 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2811 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2812 !Res.getSymA()->getSymbol().isTemporary()) {
2813 const MCExpr *CallExpr =
2814 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2815 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2816 MCOperand::createExpr(CallExpr), IDLoc, STI);
2817 return false;
2818 }
2819
2820 // The remaining cases are:
2821 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2822 // >addiu $tmp, $tmp, %lo(offset)
2823 // >addiu $rd, $tmp, $rs
2824 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2825 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2826 // >addiu $rd, $tmp, $rs
2827 // The addiu's marked with a '>' may be omitted if they are redundant. If
2828 // this happens then the last instruction must use $rd as the result
2829 // register.
2830 const MipsMCExpr *GotExpr =
2831 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2832 const MCExpr *LoExpr = nullptr;
2833 if (Res.getSymA()->getSymbol().isInSection() ||
2834 Res.getSymA()->getSymbol().isTemporary())
2835 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2836 else if (Res.getConstant() != 0) {
2837 // External symbols fully resolve the symbol with just the %got(symbol)
2838 // but we must still account for any offset to the symbol for expressions
2839 // like symbol+8.
2840 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2841 }
2842
2843 unsigned TmpReg = DstReg;
2844 if (UseSrcReg &&
2845 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2846 SrcReg)) {
2847 // If $rs is the same as $rd, we need to use AT.
2848 // If it is not available we exit.
2849 unsigned ATReg = getATReg(IDLoc);
2850 if (!ATReg)
2851 return true;
2852 TmpReg = ATReg;
2853 }
2854
2855 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2856 MCOperand::createExpr(GotExpr), IDLoc, STI);
2857
2858 if (LoExpr)
2859 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2860 IDLoc, STI);
2861
2862 if (UseSrcReg)
2863 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2864
2865 return false;
2866 }
2867
2868 const MipsMCExpr *HiExpr =
2869 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2870 const MipsMCExpr *LoExpr =
2871 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002872
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002873 // This is the 64-bit symbol address expansion.
2874 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002875 // We need AT for the 64-bit expansion in the cases where the optional
2876 // source register is the destination register and for the superscalar
2877 // scheduled form.
2878 //
2879 // If it is not available we exit if the destination is the same as the
2880 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002881
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002882 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002883 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002884 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002885 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002886
Simon Dardis3aa8a902017-02-06 12:43:46 +00002887 bool RdRegIsRsReg =
2888 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2889
2890 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2891 unsigned ATReg = getATReg(IDLoc);
2892
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002893 // If $rs is the same as $rd:
2894 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2895 // daddiu $at, $at, %higher(sym)
2896 // dsll $at, $at, 16
2897 // daddiu $at, $at, %hi(sym)
2898 // dsll $at, $at, 16
2899 // daddiu $at, $at, %lo(sym)
2900 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002901 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2902 STI);
2903 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2904 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2905 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2906 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2907 IDLoc, STI);
2908 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2909 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2910 IDLoc, STI);
2911 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002912
2913 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00002914 } else if (canUseATReg() && !RdRegIsRsReg) {
2915 unsigned ATReg = getATReg(IDLoc);
2916
2917 // If the $rs is different from $rd or if $rs isn't specified and we
2918 // have $at available:
2919 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2920 // lui $at, %hi(sym)
2921 // daddiu $rd, $rd, %higher(sym)
2922 // daddiu $at, $at, %lo(sym)
2923 // dsll32 $rd, $rd, 0
2924 // daddu $rd, $rd, $at
2925 // (daddu $rd, $rd, $rs)
2926 //
2927 // Which is preferred for superscalar issue.
2928 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2929 STI);
2930 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2931 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2932 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2933 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2934 IDLoc, STI);
2935 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2936 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
2937 if (UseSrcReg)
2938 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2939
2940 return false;
2941 } else if (!canUseATReg() && !RdRegIsRsReg) {
2942 // Otherwise, synthesize the address in the destination register
2943 // serially:
2944 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2945 // daddiu $rd, $rd, %higher(sym)
2946 // dsll $rd, $rd, 16
2947 // daddiu $rd, $rd, %hi(sym)
2948 // dsll $rd, $rd, 16
2949 // daddiu $rd, $rd, %lo(sym)
2950 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2951 STI);
2952 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2953 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2954 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2955 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2956 MCOperand::createExpr(HiExpr), IDLoc, STI);
2957 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2958 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2959 MCOperand::createExpr(LoExpr), IDLoc, STI);
2960 if (UseSrcReg)
2961 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2962
2963 return false;
2964 } else {
2965 // We have a case where SrcReg == DstReg and we don't have $at
2966 // available. We can't expand this case, so error out appropriately.
2967 assert(SrcReg == DstReg && !canUseATReg() &&
2968 "Could have expanded dla but didn't?");
2969 reportParseError(IDLoc,
2970 "pseudo-instruction requires $at, which is not available");
2971 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002972 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002973 }
2974
2975 // And now, the 32-bit symbol address expansion:
2976 // If $rs is the same as $rd:
2977 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2978 // ori $at, $at, %lo(sym)
2979 // addu $rd, $at, $rd
2980 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2981 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2982 // ori $rd, $rd, %lo(sym)
2983 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002984 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002985 if (UseSrcReg &&
2986 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002987 // If $rs is the same as $rd, we need to use AT.
2988 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002989 unsigned ATReg = getATReg(IDLoc);
2990 if (!ATReg)
2991 return true;
2992 TmpReg = ATReg;
2993 }
2994
Daniel Sandersa736b372016-04-29 13:33:12 +00002995 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2996 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2997 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002998
Toma Tabacufb9d1252015-06-22 12:08:39 +00002999 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003000 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003001 else
Scott Egerton24557012016-01-21 15:11:01 +00003002 assert(
3003 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003004
Toma Tabacu674825c2015-06-16 12:16:24 +00003005 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003006}
3007
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003008// Each double-precision register DO-D15 overlaps with two of the single
3009// precision registers F0-F31. As an example, all of the following hold true:
3010// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3011static unsigned nextReg(unsigned Reg) {
3012 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3013 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3014 switch (Reg) {
3015 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3016 case Mips::ZERO: return Mips::AT;
3017 case Mips::AT: return Mips::V0;
3018 case Mips::V0: return Mips::V1;
3019 case Mips::V1: return Mips::A0;
3020 case Mips::A0: return Mips::A1;
3021 case Mips::A1: return Mips::A2;
3022 case Mips::A2: return Mips::A3;
3023 case Mips::A3: return Mips::T0;
3024 case Mips::T0: return Mips::T1;
3025 case Mips::T1: return Mips::T2;
3026 case Mips::T2: return Mips::T3;
3027 case Mips::T3: return Mips::T4;
3028 case Mips::T4: return Mips::T5;
3029 case Mips::T5: return Mips::T6;
3030 case Mips::T6: return Mips::T7;
3031 case Mips::T7: return Mips::S0;
3032 case Mips::S0: return Mips::S1;
3033 case Mips::S1: return Mips::S2;
3034 case Mips::S2: return Mips::S3;
3035 case Mips::S3: return Mips::S4;
3036 case Mips::S4: return Mips::S5;
3037 case Mips::S5: return Mips::S6;
3038 case Mips::S6: return Mips::S7;
3039 case Mips::S7: return Mips::T8;
3040 case Mips::T8: return Mips::T9;
3041 case Mips::T9: return Mips::K0;
3042 case Mips::K0: return Mips::K1;
3043 case Mips::K1: return Mips::GP;
3044 case Mips::GP: return Mips::SP;
3045 case Mips::SP: return Mips::FP;
3046 case Mips::FP: return Mips::RA;
3047 case Mips::RA: return Mips::ZERO;
3048 case Mips::D0: return Mips::F1;
3049 case Mips::D1: return Mips::F3;
3050 case Mips::D2: return Mips::F5;
3051 case Mips::D3: return Mips::F7;
3052 case Mips::D4: return Mips::F9;
3053 case Mips::D5: return Mips::F11;
3054 case Mips::D6: return Mips::F13;
3055 case Mips::D7: return Mips::F15;
3056 case Mips::D8: return Mips::F17;
3057 case Mips::D9: return Mips::F19;
3058 case Mips::D10: return Mips::F21;
3059 case Mips::D11: return Mips::F23;
3060 case Mips::D12: return Mips::F25;
3061 case Mips::D13: return Mips::F27;
3062 case Mips::D14: return Mips::F29;
3063 case Mips::D15: return Mips::F31;
3064 }
3065}
3066
3067// FIXME: This method is too general. In principle we should compute the number
3068// of instructions required to synthesize the immediate inline compared to
3069// synthesizing the address inline and relying on non .text sections.
3070// For static O32 and N32 this may yield a small benefit, for static N64 this is
3071// likely to yield a much larger benefit as we have to synthesize a 64bit
3072// address to load a 64 bit value.
3073bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3074 MCSymbol *Sym) {
3075 unsigned ATReg = getATReg(IDLoc);
3076 if (!ATReg)
3077 return true;
3078
3079 if(IsPicEnabled) {
3080 const MCExpr *GotSym =
3081 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3082 const MipsMCExpr *GotExpr =
3083 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3084
3085 if(isABI_O32() || isABI_N32()) {
3086 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3087 IDLoc, STI);
3088 } else { //isABI_N64()
3089 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3090 IDLoc, STI);
3091 }
3092 } else { //!IsPicEnabled
3093 const MCExpr *HiSym =
3094 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3095 const MipsMCExpr *HiExpr =
3096 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3097
3098 // FIXME: This is technically correct but gives a different result to gas,
3099 // but gas is incomplete there (it has a fixme noting it doesn't work with
3100 // 64-bit addresses).
3101 // FIXME: With -msym32 option, the address expansion for N64 should probably
3102 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3103 // symbol's value is considered sign extended.
3104 if(isABI_O32() || isABI_N32()) {
3105 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3106 } else { //isABI_N64()
3107 const MCExpr *HighestSym =
3108 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3109 const MipsMCExpr *HighestExpr =
3110 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3111 const MCExpr *HigherSym =
3112 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3113 const MipsMCExpr *HigherExpr =
3114 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3115
3116 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3117 STI);
3118 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3119 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3120 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3121 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3122 IDLoc, STI);
3123 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3124 }
3125 }
3126 return false;
3127}
3128
3129bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3130 bool Is64FPU, SMLoc IDLoc,
3131 MCStreamer &Out,
3132 const MCSubtargetInfo *STI) {
3133 MipsTargetStreamer &TOut = getTargetStreamer();
3134 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3135 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3136 "Invalid instruction operand.");
3137
3138 unsigned FirstReg = Inst.getOperand(0).getReg();
3139 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3140
3141 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3142 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3143 // exponent field), convert it to double (e.g. 1 to 1.0)
3144 if ((HiImmOp64 & 0x7ff00000) == 0) {
3145 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3146 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3147 }
3148
3149 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3150 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3151
3152 if (IsSingle) {
3153 // Conversion of a double in an uint64_t to a float in a uint32_t,
3154 // retaining the bit pattern of a float.
3155 uint32_t ImmOp32;
3156 double doubleImm = BitsToDouble(ImmOp64);
3157 float tmp_float = static_cast<float>(doubleImm);
3158 ImmOp32 = FloatToBits(tmp_float);
3159
3160 if (IsGPR) {
3161 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3162 Out, STI))
3163 return true;
3164 return false;
3165 } else {
3166 unsigned ATReg = getATReg(IDLoc);
3167 if (!ATReg)
3168 return true;
3169 if (LoImmOp64 == 0) {
3170 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3171 Out, STI))
3172 return true;
3173 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3174 return false;
3175 }
3176
3177 MCSection *CS = getStreamer().getCurrentSectionOnly();
3178 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3179 // where appropriate.
3180 MCSection *ReadOnlySection = getContext().getELFSection(
3181 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3182
3183 MCSymbol *Sym = getContext().createTempSymbol();
3184 const MCExpr *LoSym =
3185 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3186 const MipsMCExpr *LoExpr =
3187 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3188
3189 getStreamer().SwitchSection(ReadOnlySection);
3190 getStreamer().EmitLabel(Sym, IDLoc);
3191 getStreamer().EmitIntValue(ImmOp32, 4);
3192 getStreamer().SwitchSection(CS);
3193
3194 if(emitPartialAddress(TOut, IDLoc, Sym))
3195 return true;
3196 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3197 MCOperand::createExpr(LoExpr), IDLoc, STI);
3198 }
3199 return false;
3200 }
3201
3202 // if(!IsSingle)
3203 unsigned ATReg = getATReg(IDLoc);
3204 if (!ATReg)
3205 return true;
3206
3207 if (IsGPR) {
3208 if (LoImmOp64 == 0) {
3209 if(isABI_N32() || isABI_N64()) {
3210 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3211 IDLoc, Out, STI))
3212 return true;
3213 return false;
3214 } else {
3215 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3216 IDLoc, Out, STI))
3217 return true;
3218
3219 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3220 IDLoc, Out, STI))
3221 return true;
3222 return false;
3223 }
3224 }
3225
3226 MCSection *CS = getStreamer().getCurrentSectionOnly();
3227 MCSection *ReadOnlySection = getContext().getELFSection(
3228 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3229
3230 MCSymbol *Sym = getContext().createTempSymbol();
3231 const MCExpr *LoSym =
3232 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3233 const MipsMCExpr *LoExpr =
3234 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3235
3236 getStreamer().SwitchSection(ReadOnlySection);
3237 getStreamer().EmitLabel(Sym, IDLoc);
3238 getStreamer().EmitIntValue(HiImmOp64, 4);
3239 getStreamer().EmitIntValue(LoImmOp64, 4);
3240 getStreamer().SwitchSection(CS);
3241
3242 if(emitPartialAddress(TOut, IDLoc, Sym))
3243 return true;
3244 if(isABI_N64())
3245 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3246 MCOperand::createExpr(LoExpr), IDLoc, STI);
3247 else
3248 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3249 MCOperand::createExpr(LoExpr), IDLoc, STI);
3250
3251 if(isABI_N32() || isABI_N64())
3252 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3253 else {
3254 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3255 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3256 }
3257 return false;
3258 } else { // if(!IsGPR && !IsSingle)
3259 if ((LoImmOp64 == 0) &&
3260 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3261 // FIXME: In the case where the constant is zero, we can load the
3262 // register directly from the zero register.
3263 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3264 Out, STI))
3265 return true;
3266 if (isABI_N32() || isABI_N64())
3267 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3268 else if (hasMips32r2()) {
3269 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3270 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3271 } else {
3272 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3273 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3274 }
3275 return false;
3276 }
3277
3278 MCSection *CS = getStreamer().getCurrentSectionOnly();
3279 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3280 // where appropriate.
3281 MCSection *ReadOnlySection = getContext().getELFSection(
3282 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3283
3284 MCSymbol *Sym = getContext().createTempSymbol();
3285 const MCExpr *LoSym =
3286 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3287 const MipsMCExpr *LoExpr =
3288 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3289
3290 getStreamer().SwitchSection(ReadOnlySection);
3291 getStreamer().EmitLabel(Sym, IDLoc);
3292 getStreamer().EmitIntValue(HiImmOp64, 4);
3293 getStreamer().EmitIntValue(LoImmOp64, 4);
3294 getStreamer().SwitchSection(CS);
3295
3296 if(emitPartialAddress(TOut, IDLoc, Sym))
3297 return true;
3298 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3299 MCOperand::createExpr(LoExpr), IDLoc, STI);
3300 }
3301 return false;
3302}
3303
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003304bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3305 MCStreamer &Out,
3306 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003307 MipsTargetStreamer &TOut = getTargetStreamer();
3308
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003309 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3310 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003311
3312 MCOperand Offset = Inst.getOperand(0);
3313 if (Offset.isExpr()) {
3314 Inst.clear();
3315 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003316 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3317 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3318 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003319 } else {
3320 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003321 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003322 // If offset fits into 11 bits then this instruction becomes microMIPS
3323 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003324 if (inMicroMipsMode())
3325 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003326 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003327 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003328 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003329 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003330 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003331 Inst.clear();
3332 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003333 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3334 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3335 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003336 }
3337 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003338 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003339
Zoran Jovanovicada70912015-09-07 11:56:37 +00003340 // If .set reorder is active and branch instruction has a delay slot,
3341 // emit a NOP after it.
3342 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3343 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003344 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003345
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003346 return false;
3347}
3348
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003349bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3350 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003351 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003352 const MCOperand &DstRegOp = Inst.getOperand(0);
3353 assert(DstRegOp.isReg() && "expected register operand kind");
3354
3355 const MCOperand &ImmOp = Inst.getOperand(1);
3356 assert(ImmOp.isImm() && "expected immediate operand kind");
3357
3358 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003359 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3360 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003361
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003362 bool IsLikely = false;
3363
Toma Tabacue1e460d2015-06-11 10:36:10 +00003364 unsigned OpCode = 0;
3365 switch(Inst.getOpcode()) {
3366 case Mips::BneImm:
3367 OpCode = Mips::BNE;
3368 break;
3369 case Mips::BeqImm:
3370 OpCode = Mips::BEQ;
3371 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003372 case Mips::BEQLImmMacro:
3373 OpCode = Mips::BEQL;
3374 IsLikely = true;
3375 break;
3376 case Mips::BNELImmMacro:
3377 OpCode = Mips::BNEL;
3378 IsLikely = true;
3379 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003380 default:
3381 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3382 break;
3383 }
3384
3385 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003386 if (ImmValue == 0) {
3387 if (IsLikely) {
3388 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3389 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3390 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3391 } else
3392 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3393 STI);
3394 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003395 warnIfNoMacro(IDLoc);
3396
3397 unsigned ATReg = getATReg(IDLoc);
3398 if (!ATReg)
3399 return true;
3400
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003401 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003402 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003403 return true;
3404
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003405 if (IsLikely) {
3406 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3407 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3408 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3409 } else
3410 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003411 }
3412 return false;
3413}
3414
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003415void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003416 const MCSubtargetInfo *STI, bool IsLoad,
3417 bool IsImmOpnd) {
3418 if (IsLoad) {
3419 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3420 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003421 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003422 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3423}
3424
3425void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3426 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3427 MipsTargetStreamer &TOut = getTargetStreamer();
3428
3429 unsigned DstReg = Inst.getOperand(0).getReg();
3430 unsigned BaseReg = Inst.getOperand(1).getReg();
3431
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003432 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003433 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3434 unsigned DstRegClassID =
3435 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3436 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3437 (DstRegClassID == Mips::GPR64RegClassID);
3438
3439 if (IsImmOpnd) {
3440 // Try to use DstReg as the temporary.
3441 if (IsGPR && (BaseReg != DstReg)) {
3442 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3443 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3444 STI);
3445 return;
3446 }
3447
Matheus Almeida7de68e72014-06-18 14:46:05 +00003448 // At this point we need AT to perform the expansions and we exit if it is
3449 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003450 unsigned ATReg = getATReg(IDLoc);
3451 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003452 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003453
3454 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3455 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3456 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003457 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003458
Daniel Sandersfba875f2016-04-29 13:43:45 +00003459 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003460 MCOperand LoOperand = MCOperand::createExpr(
3461 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3462 MCOperand HiOperand = MCOperand::createExpr(
3463 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003464
3465 // Try to use DstReg as the temporary.
3466 if (IsGPR && (BaseReg != DstReg)) {
3467 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3468 LoOperand, DstReg, IDLoc, STI);
3469 return;
3470 }
3471
3472 // At this point we need AT to perform the expansions and we exit if it is
3473 // not available.
3474 unsigned ATReg = getATReg(IDLoc);
3475 if (!ATReg)
3476 return;
3477
3478 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3479 LoOperand, ATReg, IDLoc, STI);
3480}
3481
3482void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3483 const MCSubtargetInfo *STI,
3484 bool IsImmOpnd) {
3485 MipsTargetStreamer &TOut = getTargetStreamer();
3486
3487 unsigned SrcReg = Inst.getOperand(0).getReg();
3488 unsigned BaseReg = Inst.getOperand(1).getReg();
3489
Daniel Sanders241c6792016-05-12 14:01:50 +00003490 if (IsImmOpnd) {
3491 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3492 Inst.getOperand(2).getImm(),
3493 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3494 return;
3495 }
3496
Daniel Sandersfba875f2016-04-29 13:43:45 +00003497 unsigned ATReg = getATReg(IDLoc);
3498 if (!ATReg)
3499 return;
3500
Daniel Sandersfba875f2016-04-29 13:43:45 +00003501 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003502 MCOperand LoOperand = MCOperand::createExpr(
3503 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3504 MCOperand HiOperand = MCOperand::createExpr(
3505 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003506 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3507 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003508}
3509
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003510bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3511 MCStreamer &Out,
3512 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003513 unsigned OpNum = Inst.getNumOperands();
3514 unsigned Opcode = Inst.getOpcode();
3515 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3516
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003517 assert(Inst.getOperand(OpNum - 1).isImm() &&
3518 Inst.getOperand(OpNum - 2).isReg() &&
3519 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003520
3521 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3522 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003523 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3524 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3525 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3526 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003527 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003528 if (inMicroMipsMode() && hasMips32r6())
3529 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3530 else
3531 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3532 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003533
3534 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003535 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003536 return false;
3537}
3538
Toma Tabacu1a108322015-06-17 13:20:24 +00003539bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003540 MCStreamer &Out,
3541 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003542 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003543 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003544 unsigned PseudoOpcode = Inst.getOpcode();
3545 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003546 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003547 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3548
3549 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003550 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003551
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003552 unsigned TrgReg;
3553 if (TrgOp.isReg())
3554 TrgReg = TrgOp.getReg();
3555 else if (TrgOp.isImm()) {
3556 warnIfNoMacro(IDLoc);
3557 EmittedNoMacroWarning = true;
3558
3559 TrgReg = getATReg(IDLoc);
3560 if (!TrgReg)
3561 return true;
3562
3563 switch(PseudoOpcode) {
3564 default:
3565 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3566 case Mips::BLTImmMacro:
3567 PseudoOpcode = Mips::BLT;
3568 break;
3569 case Mips::BLEImmMacro:
3570 PseudoOpcode = Mips::BLE;
3571 break;
3572 case Mips::BGEImmMacro:
3573 PseudoOpcode = Mips::BGE;
3574 break;
3575 case Mips::BGTImmMacro:
3576 PseudoOpcode = Mips::BGT;
3577 break;
3578 case Mips::BLTUImmMacro:
3579 PseudoOpcode = Mips::BLTU;
3580 break;
3581 case Mips::BLEUImmMacro:
3582 PseudoOpcode = Mips::BLEU;
3583 break;
3584 case Mips::BGEUImmMacro:
3585 PseudoOpcode = Mips::BGEU;
3586 break;
3587 case Mips::BGTUImmMacro:
3588 PseudoOpcode = Mips::BGTU;
3589 break;
3590 case Mips::BLTLImmMacro:
3591 PseudoOpcode = Mips::BLTL;
3592 break;
3593 case Mips::BLELImmMacro:
3594 PseudoOpcode = Mips::BLEL;
3595 break;
3596 case Mips::BGELImmMacro:
3597 PseudoOpcode = Mips::BGEL;
3598 break;
3599 case Mips::BGTLImmMacro:
3600 PseudoOpcode = Mips::BGTL;
3601 break;
3602 case Mips::BLTULImmMacro:
3603 PseudoOpcode = Mips::BLTUL;
3604 break;
3605 case Mips::BLEULImmMacro:
3606 PseudoOpcode = Mips::BLEUL;
3607 break;
3608 case Mips::BGEULImmMacro:
3609 PseudoOpcode = Mips::BGEUL;
3610 break;
3611 case Mips::BGTULImmMacro:
3612 PseudoOpcode = Mips::BGTUL;
3613 break;
3614 }
3615
3616 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003617 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003618 return true;
3619 }
3620
Toma Tabacu1a108322015-06-17 13:20:24 +00003621 switch (PseudoOpcode) {
3622 case Mips::BLT:
3623 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003624 case Mips::BLTL:
3625 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003626 AcceptsEquality = false;
3627 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003628 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3629 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003630 ZeroSrcOpcode = Mips::BGTZ;
3631 ZeroTrgOpcode = Mips::BLTZ;
3632 break;
3633 case Mips::BLE:
3634 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003635 case Mips::BLEL:
3636 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003637 AcceptsEquality = true;
3638 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003639 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3640 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003641 ZeroSrcOpcode = Mips::BGEZ;
3642 ZeroTrgOpcode = Mips::BLEZ;
3643 break;
3644 case Mips::BGE:
3645 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003646 case Mips::BGEL:
3647 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003648 AcceptsEquality = true;
3649 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003650 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3651 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003652 ZeroSrcOpcode = Mips::BLEZ;
3653 ZeroTrgOpcode = Mips::BGEZ;
3654 break;
3655 case Mips::BGT:
3656 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003657 case Mips::BGTL:
3658 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003659 AcceptsEquality = false;
3660 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003661 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3662 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003663 ZeroSrcOpcode = Mips::BLTZ;
3664 ZeroTrgOpcode = Mips::BGTZ;
3665 break;
3666 default:
3667 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3668 }
3669
Toma Tabacu1a108322015-06-17 13:20:24 +00003670 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3671 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3672 if (IsSrcRegZero && IsTrgRegZero) {
3673 // FIXME: All of these Opcode-specific if's are needed for compatibility
3674 // with GAS' behaviour. However, they may not generate the most efficient
3675 // code in some circumstances.
3676 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003677 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3678 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003679 return false;
3680 }
3681 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003682 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3683 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003684 Warning(IDLoc, "branch is always taken");
3685 return false;
3686 }
3687 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003688 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3689 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003690 Warning(IDLoc, "branch is always taken");
3691 return false;
3692 }
3693 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003694 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3695 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003696 return false;
3697 }
3698 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003699 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3700 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003701 return false;
3702 }
3703 if (AcceptsEquality) {
3704 // If both registers are $0 and the pseudo-branch accepts equality, it
3705 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003706 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3707 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003708 Warning(IDLoc, "branch is always taken");
3709 return false;
3710 }
3711 // If both registers are $0 and the pseudo-branch does not accept
3712 // equality, it will never be taken, so we don't have to emit anything.
3713 return false;
3714 }
3715 if (IsSrcRegZero || IsTrgRegZero) {
3716 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3717 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3718 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3719 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3720 // the pseudo-branch will never be taken, so we don't emit anything.
3721 // This only applies to unsigned pseudo-branches.
3722 return false;
3723 }
3724 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3725 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3726 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3727 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3728 // the pseudo-branch will always be taken, so we emit an unconditional
3729 // branch.
3730 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003731 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3732 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003733 Warning(IDLoc, "branch is always taken");
3734 return false;
3735 }
3736 if (IsUnsigned) {
3737 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3738 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3739 // the pseudo-branch will be taken only when the non-zero register is
3740 // different from 0, so we emit a BNEZ.
3741 //
3742 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3743 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3744 // the pseudo-branch will be taken only when the non-zero register is
3745 // equal to 0, so we emit a BEQZ.
3746 //
3747 // Because only BLEU and BGEU branch on equality, we can use the
3748 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003749 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3750 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3751 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003752 return false;
3753 }
3754 // If we have a signed pseudo-branch and one of the registers is $0,
3755 // we can use an appropriate compare-to-zero branch. We select which one
3756 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003757 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3758 IsSrcRegZero ? TrgReg : SrcReg,
3759 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003760 return false;
3761 }
3762
3763 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3764 // expansions. If it is not available, we return.
3765 unsigned ATRegNum = getATReg(IDLoc);
3766 if (!ATRegNum)
3767 return true;
3768
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003769 if (!EmittedNoMacroWarning)
3770 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003771
3772 // SLT fits well with 2 of our 4 pseudo-branches:
3773 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3774 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3775 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3776 // This is accomplished by using a BNEZ with the result of the SLT.
3777 //
3778 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3779 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3780 // Because only BGE and BLE branch on equality, we can use the
3781 // AcceptsEquality variable to decide when to emit the BEQZ.
3782 // Note that the order of the SLT arguments doesn't change between
3783 // opposites.
3784 //
3785 // The same applies to the unsigned variants, except that SLTu is used
3786 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003787 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3788 ReverseOrderSLT ? TrgReg : SrcReg,
3789 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003790
Daniel Sandersa736b372016-04-29 13:33:12 +00003791 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3792 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3793 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3794 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003795 return false;
3796}
3797
Simon Dardis509da1a2017-02-13 16:06:48 +00003798// Expand a integer division macro.
3799//
3800// Notably we don't have to emit a warning when encountering $rt as the $zero
3801// register, or 0 as an immediate. processInstruction() has already done that.
3802//
3803// The destination register can only be $zero when expanding (S)DivIMacro or
3804// D(S)DivMacro.
3805
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003806bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3807 const MCSubtargetInfo *STI, const bool IsMips64,
3808 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003809 MipsTargetStreamer &TOut = getTargetStreamer();
3810
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003811 warnIfNoMacro(IDLoc);
3812
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003813 const MCOperand &RdRegOp = Inst.getOperand(0);
3814 assert(RdRegOp.isReg() && "expected register operand kind");
3815 unsigned RdReg = RdRegOp.getReg();
3816
3817 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003818 assert(RsRegOp.isReg() && "expected register operand kind");
3819 unsigned RsReg = RsRegOp.getReg();
3820
Simon Dardis12850ee2017-01-31 10:49:24 +00003821 unsigned RtReg;
3822 int64_t ImmValue;
3823
3824 const MCOperand &RtOp = Inst.getOperand(2);
3825 assert((RtOp.isReg() || RtOp.isImm()) &&
3826 "expected register or immediate operand kind");
3827 if (RtOp.isReg())
3828 RtReg = RtOp.getReg();
3829 else
3830 ImmValue = RtOp.getImm();
3831
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003832 unsigned DivOp;
3833 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003834 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003835
3836 if (IsMips64) {
3837 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3838 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003839 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003840 } else {
3841 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3842 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003843 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003844 }
3845
3846 bool UseTraps = useTraps();
3847
Simon Dardis12850ee2017-01-31 10:49:24 +00003848 if (RtOp.isImm()) {
3849 unsigned ATReg = getATReg(IDLoc);
3850 if (!ATReg)
3851 return true;
3852
3853 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003854 if (UseTraps)
3855 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3856 else
3857 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3858 return false;
3859 }
3860
3861 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003862 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003863 return false;
3864 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003865 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003866 return false;
3867 } else {
3868 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3869 false, Inst.getLoc(), Out, STI))
3870 return true;
3871 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3872 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3873 return false;
3874 }
3875 return true;
3876 }
3877
Simon Dardis509da1a2017-02-13 16:06:48 +00003878 // If the macro expansion of (d)div(u) would always trap or break, insert
3879 // the trap/break and exit. This gives a different result to GAS. GAS has
3880 // an inconsistency/missed optimization in that not all cases are handled
3881 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003882 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003883 if (UseTraps) {
3884 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003885 return false;
3886 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003887 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3888 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003889 }
3890
Simon Dardis509da1a2017-02-13 16:06:48 +00003891 // Temporary label for first branch traget
3892 MCContext &Context = TOut.getStreamer().getContext();
3893 MCSymbol *BrTarget;
3894 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003895
3896 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003897 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003898 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003899 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003900 BrTarget = Context.createTempSymbol();
3901 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
3902 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003903 }
3904
Daniel Sandersa736b372016-04-29 13:33:12 +00003905 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003906
3907 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003908 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003909
3910 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003911 if (!UseTraps)
3912 TOut.getStreamer().EmitLabel(BrTarget);
3913
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003914 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003915 return false;
3916 }
3917
3918 unsigned ATReg = getATReg(IDLoc);
3919 if (!ATReg)
3920 return true;
3921
Simon Dardis509da1a2017-02-13 16:06:48 +00003922 if (!UseTraps)
3923 TOut.getStreamer().EmitLabel(BrTarget);
3924
Daniel Sandersa736b372016-04-29 13:33:12 +00003925 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00003926
3927 // Temporary label for the second branch target.
3928 MCSymbol *BrTargetEnd = Context.createTempSymbol();
3929 MCOperand LabelOpEnd =
3930 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
3931
3932 // Branch to the mflo instruction.
3933 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
3934
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003935 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003936 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3937 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003938 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003939 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003940 }
3941
3942 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003943 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003944 else {
3945 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003946 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003947 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3948 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003949 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003950
3951 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003952 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003953 return false;
3954}
3955
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003956bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003957 SMLoc IDLoc, MCStreamer &Out,
3958 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003959 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003960
3961 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3962 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3963 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3964
3965 unsigned FirstReg = Inst.getOperand(0).getReg();
3966 unsigned SecondReg = Inst.getOperand(1).getReg();
3967 unsigned ThirdReg = Inst.getOperand(2).getReg();
3968
3969 if (hasMips1() && !hasMips2()) {
3970 unsigned ATReg = getATReg(IDLoc);
3971 if (!ATReg)
3972 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003973 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3974 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3975 TOut.emitNop(IDLoc, STI);
3976 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3977 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3978 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3979 TOut.emitNop(IDLoc, STI);
3980 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3981 : Mips::CVT_W_S,
3982 FirstReg, SecondReg, IDLoc, STI);
3983 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3984 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003985 return false;
3986 }
3987
Daniel Sandersa736b372016-04-29 13:33:12 +00003988 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3989 : Mips::TRUNC_W_S,
3990 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003991
3992 return false;
3993}
3994
Daniel Sanders6394ee52015-10-15 14:52:58 +00003995bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003996 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003997 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003998 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003999 }
4000
Toma Tabacud88d79c2015-06-23 14:39:42 +00004001 const MCOperand &DstRegOp = Inst.getOperand(0);
4002 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004003 const MCOperand &SrcRegOp = Inst.getOperand(1);
4004 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004005 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4006 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4007
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004008 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004009 unsigned DstReg = DstRegOp.getReg();
4010 unsigned SrcReg = SrcRegOp.getReg();
4011 int64_t OffsetValue = OffsetImmOp.getImm();
4012
4013 // NOTE: We always need AT for ULHU, as it is always used as the source
4014 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004015 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004016 unsigned ATReg = getATReg(IDLoc);
4017 if (!ATReg)
4018 return true;
4019
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004020 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4021 if (IsLargeOffset) {
4022 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4023 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004024 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004025 }
4026
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004027 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4028 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4029 if (isLittle())
4030 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004031
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004032 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4033 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004034
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004035 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4036 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004037
Daniel Sandersa736b372016-04-29 13:33:12 +00004038 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004039 FirstOffset, IDLoc, STI);
4040 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004041 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004042 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004043
4044 return false;
4045}
4046
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004047bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004048 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004049 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004050 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004051 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004052
4053 const MCOperand &DstRegOp = Inst.getOperand(0);
4054 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004055 const MCOperand &SrcRegOp = Inst.getOperand(1);
4056 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004057 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4058 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4059
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004060 MipsTargetStreamer &TOut = getTargetStreamer();
4061 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004062 unsigned SrcReg = SrcRegOp.getReg();
4063 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004064
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004065 warnIfNoMacro(IDLoc);
4066 unsigned ATReg = getATReg(IDLoc);
4067 if (!ATReg)
4068 return true;
4069
4070 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4071 if (IsLargeOffset) {
4072 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4073 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004074 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004075 }
4076
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004077 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4078 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4079 if (isLittle())
4080 std::swap(FirstOffset, SecondOffset);
4081
4082 if (IsLargeOffset) {
4083 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4084 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4085 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4086 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4087 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4088 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004089 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004090 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4091 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4092 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004093 }
4094
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004095 return false;
4096}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004097
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004098bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4099 const MCSubtargetInfo *STI) {
4100 if (hasMips32r6() || hasMips64r6()) {
4101 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4102 }
4103
4104 const MCOperand &DstRegOp = Inst.getOperand(0);
4105 assert(DstRegOp.isReg() && "expected register operand kind");
4106 const MCOperand &SrcRegOp = Inst.getOperand(1);
4107 assert(SrcRegOp.isReg() && "expected register operand kind");
4108 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4109 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4110
4111 MipsTargetStreamer &TOut = getTargetStreamer();
4112 unsigned DstReg = DstRegOp.getReg();
4113 unsigned SrcReg = SrcRegOp.getReg();
4114 int64_t OffsetValue = OffsetImmOp.getImm();
4115
4116 // Compute left/right load/store offsets.
4117 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4118 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4119 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4120 if (isLittle())
4121 std::swap(LxlOffset, LxrOffset);
4122
4123 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4124 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4125 unsigned TmpReg = SrcReg;
4126 if (IsLargeOffset || DoMove) {
4127 warnIfNoMacro(IDLoc);
4128 TmpReg = getATReg(IDLoc);
4129 if (!TmpReg)
4130 return true;
4131 }
4132
4133 if (IsLargeOffset) {
4134 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4135 IDLoc, Out, STI))
4136 return true;
4137 }
4138
4139 if (DoMove)
4140 std::swap(DstReg, TmpReg);
4141
4142 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4143 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4144 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4145 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4146
4147 if (DoMove)
4148 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004149
4150 return false;
4151}
4152
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004153bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004154 MCStreamer &Out,
4155 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004156 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004157
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004158 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4159 assert(Inst.getOperand(0).isReg() &&
4160 Inst.getOperand(1).isReg() &&
4161 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004162
4163 unsigned ATReg = Mips::NoRegister;
4164 unsigned FinalDstReg = Mips::NoRegister;
4165 unsigned DstReg = Inst.getOperand(0).getReg();
4166 unsigned SrcReg = Inst.getOperand(1).getReg();
4167 int64_t ImmValue = Inst.getOperand(2).getImm();
4168
Simon Dardisaa208812017-02-24 14:34:32 +00004169 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004170
4171 unsigned FinalOpcode = Inst.getOpcode();
4172
4173 if (DstReg == SrcReg) {
4174 ATReg = getATReg(Inst.getLoc());
4175 if (!ATReg)
4176 return true;
4177 FinalDstReg = DstReg;
4178 DstReg = ATReg;
4179 }
4180
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004181 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004182 switch (FinalOpcode) {
4183 default:
4184 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004185 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004186 FinalOpcode = Mips::ADD;
4187 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004188 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004189 FinalOpcode = Mips::ADDu;
4190 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004191 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004192 FinalOpcode = Mips::AND;
4193 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004194 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004195 FinalOpcode = Mips::NOR;
4196 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004197 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004198 FinalOpcode = Mips::OR;
4199 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004200 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004201 FinalOpcode = Mips::SLT;
4202 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004203 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004204 FinalOpcode = Mips::SLTu;
4205 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004206 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004207 FinalOpcode = Mips::XOR;
4208 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004209 case Mips::ADDi_MM:
4210 FinalOpcode = Mips::ADD_MM;
4211 break;
4212 case Mips::ADDiu_MM:
4213 FinalOpcode = Mips::ADDu_MM;
4214 break;
4215 case Mips::ANDi_MM:
4216 FinalOpcode = Mips::AND_MM;
4217 break;
4218 case Mips::ORi_MM:
4219 FinalOpcode = Mips::OR_MM;
4220 break;
4221 case Mips::SLTi_MM:
4222 FinalOpcode = Mips::SLT_MM;
4223 break;
4224 case Mips::SLTiu_MM:
4225 FinalOpcode = Mips::SLTu_MM;
4226 break;
4227 case Mips::XORi_MM:
4228 FinalOpcode = Mips::XOR_MM;
4229 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004230 case Mips::ANDi64:
4231 FinalOpcode = Mips::AND64;
4232 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004233 case Mips::NORImm64:
4234 FinalOpcode = Mips::NOR64;
4235 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004236 case Mips::ORi64:
4237 FinalOpcode = Mips::OR64;
4238 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004239 case Mips::SLTImm64:
4240 FinalOpcode = Mips::SLT64;
4241 break;
4242 case Mips::SLTUImm64:
4243 FinalOpcode = Mips::SLTu64;
4244 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004245 case Mips::XORi64:
4246 FinalOpcode = Mips::XOR64;
4247 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004248 }
4249
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004250 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004251 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004252 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004253 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004254 return false;
4255 }
4256 return true;
4257}
4258
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004259bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4260 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004261 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004262 unsigned ATReg = Mips::NoRegister;
4263 unsigned DReg = Inst.getOperand(0).getReg();
4264 unsigned SReg = Inst.getOperand(1).getReg();
4265 unsigned TReg = Inst.getOperand(2).getReg();
4266 unsigned TmpReg = DReg;
4267
4268 unsigned FirstShift = Mips::NOP;
4269 unsigned SecondShift = Mips::NOP;
4270
4271 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004272 if (DReg == SReg) {
4273 TmpReg = getATReg(Inst.getLoc());
4274 if (!TmpReg)
4275 return true;
4276 }
4277
4278 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004279 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4280 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004281 return false;
4282 }
4283
4284 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004285 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004286 return false;
4287 }
4288
4289 return true;
4290 }
4291
4292 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004293 switch (Inst.getOpcode()) {
4294 default:
4295 llvm_unreachable("unexpected instruction opcode");
4296 case Mips::ROL:
4297 FirstShift = Mips::SRLV;
4298 SecondShift = Mips::SLLV;
4299 break;
4300 case Mips::ROR:
4301 FirstShift = Mips::SLLV;
4302 SecondShift = Mips::SRLV;
4303 break;
4304 }
4305
4306 ATReg = getATReg(Inst.getLoc());
4307 if (!ATReg)
4308 return true;
4309
Daniel Sandersa736b372016-04-29 13:33:12 +00004310 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4311 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4312 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4313 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004314
4315 return false;
4316 }
4317
4318 return true;
4319}
4320
4321bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004322 MCStreamer &Out,
4323 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004324 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004325 unsigned ATReg = Mips::NoRegister;
4326 unsigned DReg = Inst.getOperand(0).getReg();
4327 unsigned SReg = Inst.getOperand(1).getReg();
4328 int64_t ImmValue = Inst.getOperand(2).getImm();
4329
4330 unsigned FirstShift = Mips::NOP;
4331 unsigned SecondShift = Mips::NOP;
4332
4333 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004334 if (Inst.getOpcode() == Mips::ROLImm) {
4335 uint64_t MaxShift = 32;
4336 uint64_t ShiftValue = ImmValue;
4337 if (ImmValue != 0)
4338 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004339 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004340 return false;
4341 }
4342
4343 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004344 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004345 return false;
4346 }
4347
4348 return true;
4349 }
4350
4351 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004352 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004353 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004354 return false;
4355 }
4356
4357 switch (Inst.getOpcode()) {
4358 default:
4359 llvm_unreachable("unexpected instruction opcode");
4360 case Mips::ROLImm:
4361 FirstShift = Mips::SLL;
4362 SecondShift = Mips::SRL;
4363 break;
4364 case Mips::RORImm:
4365 FirstShift = Mips::SRL;
4366 SecondShift = Mips::SLL;
4367 break;
4368 }
4369
4370 ATReg = getATReg(Inst.getLoc());
4371 if (!ATReg)
4372 return true;
4373
Daniel Sandersa736b372016-04-29 13:33:12 +00004374 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4375 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4376 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004377
4378 return false;
4379 }
4380
4381 return true;
4382}
4383
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004384bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4385 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004386 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004387 unsigned ATReg = Mips::NoRegister;
4388 unsigned DReg = Inst.getOperand(0).getReg();
4389 unsigned SReg = Inst.getOperand(1).getReg();
4390 unsigned TReg = Inst.getOperand(2).getReg();
4391 unsigned TmpReg = DReg;
4392
4393 unsigned FirstShift = Mips::NOP;
4394 unsigned SecondShift = Mips::NOP;
4395
4396 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004397 if (TmpReg == SReg) {
4398 TmpReg = getATReg(Inst.getLoc());
4399 if (!TmpReg)
4400 return true;
4401 }
4402
4403 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004404 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4405 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004406 return false;
4407 }
4408
4409 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004410 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004411 return false;
4412 }
4413
4414 return true;
4415 }
4416
4417 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004418 switch (Inst.getOpcode()) {
4419 default:
4420 llvm_unreachable("unexpected instruction opcode");
4421 case Mips::DROL:
4422 FirstShift = Mips::DSRLV;
4423 SecondShift = Mips::DSLLV;
4424 break;
4425 case Mips::DROR:
4426 FirstShift = Mips::DSLLV;
4427 SecondShift = Mips::DSRLV;
4428 break;
4429 }
4430
4431 ATReg = getATReg(Inst.getLoc());
4432 if (!ATReg)
4433 return true;
4434
Daniel Sandersa736b372016-04-29 13:33:12 +00004435 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4436 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4437 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4438 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004439
4440 return false;
4441 }
4442
4443 return true;
4444}
4445
4446bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004447 MCStreamer &Out,
4448 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004449 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004450 unsigned ATReg = Mips::NoRegister;
4451 unsigned DReg = Inst.getOperand(0).getReg();
4452 unsigned SReg = Inst.getOperand(1).getReg();
4453 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4454
4455 unsigned FirstShift = Mips::NOP;
4456 unsigned SecondShift = Mips::NOP;
4457
4458 MCInst TmpInst;
4459
4460 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004461 unsigned FinalOpcode = Mips::NOP;
4462 if (ImmValue == 0)
4463 FinalOpcode = Mips::DROTR;
4464 else if (ImmValue % 32 == 0)
4465 FinalOpcode = Mips::DROTR32;
4466 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4467 if (Inst.getOpcode() == Mips::DROLImm)
4468 FinalOpcode = Mips::DROTR32;
4469 else
4470 FinalOpcode = Mips::DROTR;
4471 } else if (ImmValue >= 33) {
4472 if (Inst.getOpcode() == Mips::DROLImm)
4473 FinalOpcode = Mips::DROTR;
4474 else
4475 FinalOpcode = Mips::DROTR32;
4476 }
4477
4478 uint64_t ShiftValue = ImmValue % 32;
4479 if (Inst.getOpcode() == Mips::DROLImm)
4480 ShiftValue = (32 - ImmValue % 32) % 32;
4481
Daniel Sandersa736b372016-04-29 13:33:12 +00004482 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004483
4484 return false;
4485 }
4486
4487 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004488 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004489 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004490 return false;
4491 }
4492
4493 switch (Inst.getOpcode()) {
4494 default:
4495 llvm_unreachable("unexpected instruction opcode");
4496 case Mips::DROLImm:
4497 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4498 FirstShift = Mips::DSLL;
4499 SecondShift = Mips::DSRL32;
4500 }
4501 if (ImmValue == 32) {
4502 FirstShift = Mips::DSLL32;
4503 SecondShift = Mips::DSRL32;
4504 }
4505 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4506 FirstShift = Mips::DSLL32;
4507 SecondShift = Mips::DSRL;
4508 }
4509 break;
4510 case Mips::DRORImm:
4511 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4512 FirstShift = Mips::DSRL;
4513 SecondShift = Mips::DSLL32;
4514 }
4515 if (ImmValue == 32) {
4516 FirstShift = Mips::DSRL32;
4517 SecondShift = Mips::DSLL32;
4518 }
4519 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4520 FirstShift = Mips::DSRL32;
4521 SecondShift = Mips::DSLL;
4522 }
4523 break;
4524 }
4525
4526 ATReg = getATReg(Inst.getLoc());
4527 if (!ATReg)
4528 return true;
4529
Daniel Sandersa736b372016-04-29 13:33:12 +00004530 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4531 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4532 Inst.getLoc(), STI);
4533 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004534
4535 return false;
4536 }
4537
4538 return true;
4539}
4540
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004541bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4542 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004543 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004544 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4545 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4546
Daniel Sandersa736b372016-04-29 13:33:12 +00004547 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004548 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004549 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004550 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004551 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4552 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004553
4554 return false;
4555}
4556
Simon Dardis3c82a642017-02-08 16:25:05 +00004557bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4558 const MCSubtargetInfo *STI) {
4559 MipsTargetStreamer &TOut = getTargetStreamer();
4560 unsigned ATReg = Mips::NoRegister;
4561 unsigned DstReg = Inst.getOperand(0).getReg();
4562 unsigned SrcReg = Inst.getOperand(1).getReg();
4563 int32_t ImmValue = Inst.getOperand(2).getImm();
4564
4565 ATReg = getATReg(IDLoc);
4566 if (!ATReg)
4567 return true;
4568
4569 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4570
4571 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4572 SrcReg, ATReg, IDLoc, STI);
4573
4574 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4575
4576 return false;
4577}
4578
4579bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4580 const MCSubtargetInfo *STI) {
4581 MipsTargetStreamer &TOut = getTargetStreamer();
4582 unsigned ATReg = Mips::NoRegister;
4583 unsigned DstReg = Inst.getOperand(0).getReg();
4584 unsigned SrcReg = Inst.getOperand(1).getReg();
4585 unsigned TmpReg = Inst.getOperand(2).getReg();
4586
4587 ATReg = getATReg(Inst.getLoc());
4588 if (!ATReg)
4589 return true;
4590
4591 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4592 SrcReg, TmpReg, IDLoc, STI);
4593
4594 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4595
4596 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4597 DstReg, DstReg, 0x1F, IDLoc, STI);
4598
4599 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4600
4601 if (useTraps()) {
4602 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4603 } else {
4604 MCContext & Context = TOut.getStreamer().getContext();
4605 MCSymbol * BrTarget = Context.createTempSymbol();
4606 MCOperand LabelOp =
4607 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4608
4609 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4610 if (AssemblerOptions.back()->isReorder())
4611 TOut.emitNop(IDLoc, STI);
4612 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4613
4614 TOut.getStreamer().EmitLabel(BrTarget);
4615 }
4616 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4617
4618 return false;
4619}
4620
4621bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4622 const MCSubtargetInfo *STI) {
4623 MipsTargetStreamer &TOut = getTargetStreamer();
4624 unsigned ATReg = Mips::NoRegister;
4625 unsigned DstReg = Inst.getOperand(0).getReg();
4626 unsigned SrcReg = Inst.getOperand(1).getReg();
4627 unsigned TmpReg = Inst.getOperand(2).getReg();
4628
4629 ATReg = getATReg(IDLoc);
4630 if (!ATReg)
4631 return true;
4632
4633 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4634 SrcReg, TmpReg, IDLoc, STI);
4635
4636 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4637 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4638 if (useTraps()) {
4639 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4640 } else {
4641 MCContext & Context = TOut.getStreamer().getContext();
4642 MCSymbol * BrTarget = Context.createTempSymbol();
4643 MCOperand LabelOp =
4644 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4645
4646 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4647 if (AssemblerOptions.back()->isReorder())
4648 TOut.emitNop(IDLoc, STI);
4649 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4650
4651 TOut.getStreamer().EmitLabel(BrTarget);
4652 }
4653
4654 return false;
4655}
4656
4657bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4658 const MCSubtargetInfo *STI) {
4659 MipsTargetStreamer &TOut = getTargetStreamer();
4660 unsigned DstReg = Inst.getOperand(0).getReg();
4661 unsigned SrcReg = Inst.getOperand(1).getReg();
4662 unsigned TmpReg = Inst.getOperand(2).getReg();
4663
4664 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4665 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4666
4667 return false;
4668}
4669
Simon Dardisaff4d142016-10-18 14:28:00 +00004670// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4671// lw $<reg+1>>, offset+4($reg2)'
4672// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4673// sw $<reg+1>>, offset+4($reg2)'
4674// for O32.
4675bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4676 MCStreamer &Out,
4677 const MCSubtargetInfo *STI,
4678 bool IsLoad) {
4679 if (!isABI_O32())
4680 return true;
4681
4682 warnIfNoMacro(IDLoc);
4683
4684 MipsTargetStreamer &TOut = getTargetStreamer();
4685 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4686 unsigned FirstReg = Inst.getOperand(0).getReg();
4687 unsigned SecondReg = nextReg(FirstReg);
4688 unsigned BaseReg = Inst.getOperand(1).getReg();
4689 if (!SecondReg)
4690 return true;
4691
4692 warnIfRegIndexIsAT(FirstReg, IDLoc);
4693
4694 assert(Inst.getOperand(2).isImm() &&
4695 "Offset for load macro is not immediate!");
4696
4697 MCOperand &FirstOffset = Inst.getOperand(2);
4698 signed NextOffset = FirstOffset.getImm() + 4;
4699 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4700
4701 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4702 return true;
4703
4704 // For loads, clobber the base register with the second load instead of the
4705 // first if the BaseReg == FirstReg.
4706 if (FirstReg != BaseReg || !IsLoad) {
4707 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4708 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4709 } else {
4710 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4711 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4712 }
4713
4714 return false;
4715}
4716
Simon Dardis43115a12016-11-21 20:30:41 +00004717bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4718 const MCSubtargetInfo *STI) {
4719
4720 warnIfNoMacro(IDLoc);
4721 MipsTargetStreamer &TOut = getTargetStreamer();
4722
4723 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4724 Inst.getOperand(2).getReg() != Mips::ZERO) {
4725 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4726 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4727 IDLoc, STI);
4728 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4729 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4730 return false;
4731 }
4732
4733 unsigned Reg = 0;
4734 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4735 Reg = Inst.getOperand(2).getReg();
4736 } else {
4737 Reg = Inst.getOperand(1).getReg();
4738 }
4739 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4740 return false;
4741}
4742
4743bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4744 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004745 warnIfNoMacro(IDLoc);
4746 MipsTargetStreamer &TOut = getTargetStreamer();
4747
4748 unsigned Opc;
4749 int64_t Imm = Inst.getOperand(2).getImm();
4750 unsigned Reg = Inst.getOperand(1).getReg();
4751
4752 if (Imm == 0) {
4753 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4754 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4755 return false;
4756 } else {
4757
4758 if (Reg == Mips::ZERO) {
4759 Warning(IDLoc, "comparison is always false");
4760 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4761 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4762 return false;
4763 }
4764
4765 if (Imm > -0x8000 && Imm < 0) {
4766 Imm = -Imm;
4767 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4768 } else {
4769 Opc = Mips::XORi;
4770 }
4771 }
4772 if (!isUInt<16>(Imm)) {
4773 unsigned ATReg = getATReg(IDLoc);
4774 if (!ATReg)
4775 return true;
4776
4777 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4778 Out, STI))
4779 return true;
4780
4781 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4782 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4783 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4784 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4785 return false;
4786 }
4787
4788 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4789 Imm, IDLoc, STI);
4790 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4791 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4792 return false;
4793}
4794
Daniel Sandersc5537422016-07-27 13:49:44 +00004795unsigned
4796MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4797 const OperandVector &Operands) {
4798 switch (Inst.getOpcode()) {
4799 default:
4800 return Match_Success;
4801 case Mips::DATI:
4802 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004803 case Mips::DATI_MM64R6:
4804 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004805 if (static_cast<MipsOperand &>(*Operands[1])
4806 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4807 return Match_Success;
4808 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004809 }
4810}
Simon Dardis730fdb72017-01-16 13:55:58 +00004811
Matheus Almeida595fcab2014-06-11 15:05:56 +00004812unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004813 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004814 // As described by the MIPSR6 spec, daui must not use the zero operand for
4815 // its source operand.
4816 case Mips::DAUI:
4817 case Mips::DAUI_MM64R6:
4818 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4819 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4820 return Match_RequiresNoZeroRegister;
4821 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004822 // As described by the Mips32r2 spec, the registers Rd and Rs for
4823 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004824 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004825 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004826 case Mips::JALR_HB:
4827 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004828 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004829 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4830 return Match_RequiresDifferentSrcAndDst;
4831 return Match_Success;
4832 case Mips::LWP_MM:
4833 case Mips::LWP_MMR6:
4834 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4835 return Match_RequiresDifferentSrcAndDst;
4836 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004837 case Mips::SYNC:
4838 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4839 return Match_NonZeroOperandForSync;
4840 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004841 // As described the MIPSR6 spec, the compact branches that compare registers
4842 // must:
4843 // a) Not use the zero register.
4844 // b) Not use the same register twice.
4845 // c) rs < rt for bnec, beqc.
4846 // NB: For this case, the encoding will swap the operands as their
4847 // ordering doesn't matter. GAS performs this transformation too.
4848 // Hence, that constraint does not have to be enforced.
4849 //
4850 // The compact branches that branch iff the signed addition of two registers
4851 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4852 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004853 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4854 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4855 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4856 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4857 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4858 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004859 case Mips::BLEZC64:
4860 case Mips::BGEZC64:
4861 case Mips::BGTZC64:
4862 case Mips::BLTZC64:
4863 case Mips::BEQZC64:
4864 case Mips::BNEZC64:
4865 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4866 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004867 return Match_RequiresNoZeroRegister;
4868 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004869 case Mips::BGEC: case Mips::BGEC_MMR6:
4870 case Mips::BLTC: case Mips::BLTC_MMR6:
4871 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4872 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4873 case Mips::BEQC: case Mips::BEQC_MMR6:
4874 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004875 case Mips::BGEC64:
4876 case Mips::BLTC64:
4877 case Mips::BGEUC64:
4878 case Mips::BLTUC64:
4879 case Mips::BEQC64:
4880 case Mips::BNEC64:
4881 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4882 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004883 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004884 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4885 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004886 return Match_RequiresNoZeroRegister;
4887 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4888 return Match_RequiresDifferentOperands;
4889 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004890 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004891
4892 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4893 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4894 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4895 return Match_NoFCCRegisterForCurrentISA;
4896
4897 return Match_Success;
4898
Matheus Almeida595fcab2014-06-11 15:05:56 +00004899}
4900
Daniel Sanders52da7af2015-11-06 12:11:03 +00004901static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4902 uint64_t ErrorInfo) {
4903 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4904 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4905 if (ErrorLoc == SMLoc())
4906 return Loc;
4907 return ErrorLoc;
4908 }
4909 return Loc;
4910}
4911
David Blaikie960ea3f2014-06-08 16:18:35 +00004912bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4913 OperandVector &Operands,
4914 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004915 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004916 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004917 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004918 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004919 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004920
4921 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004922 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004923 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004924 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004925 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00004926 case Match_MissingFeature:
4927 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4928 return true;
4929 case Match_InvalidOperand: {
4930 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004931 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004932 if (ErrorInfo >= Operands.size())
4933 return Error(IDLoc, "too few operands for instruction");
4934
Daniel Sanders52da7af2015-11-06 12:11:03 +00004935 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004936 if (ErrorLoc == SMLoc())
4937 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004938 }
4939
4940 return Error(ErrorLoc, "invalid operand for instruction");
4941 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004942 case Match_NonZeroOperandForSync:
4943 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004944 case Match_MnemonicFail:
4945 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004946 case Match_RequiresDifferentSrcAndDst:
4947 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004948 case Match_RequiresDifferentOperands:
4949 return Error(IDLoc, "registers must be different");
4950 case Match_RequiresNoZeroRegister:
4951 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004952 case Match_RequiresSameSrcAndDst:
4953 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00004954 case Match_NoFCCRegisterForCurrentISA:
4955 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4956 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004957 case Match_Immz:
4958 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004959 case Match_UImm1_0:
4960 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4961 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004962 case Match_UImm2_0:
4963 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4964 "expected 2-bit unsigned immediate");
4965 case Match_UImm2_1:
4966 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4967 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004968 case Match_UImm3_0:
4969 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4970 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004971 case Match_UImm4_0:
4972 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4973 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004974 case Match_SImm4_0:
4975 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4976 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004977 case Match_UImm5_0:
4978 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4979 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004980 case Match_SImm5_0:
4981 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4982 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004983 case Match_UImm5_1:
4984 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4985 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004986 case Match_UImm5_32:
4987 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4988 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004989 case Match_UImm5_33:
4990 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4991 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004992 case Match_UImm5_0_Report_UImm6:
4993 // This is used on UImm5 operands that have a corresponding UImm5_32
4994 // operand to avoid confusing the user.
4995 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4996 "expected 6-bit unsigned immediate");
4997 case Match_UImm5_Lsl2:
4998 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4999 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005000 case Match_UImmRange2_64:
5001 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5002 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005003 case Match_UImm6_0:
5004 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5005 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005006 case Match_UImm6_Lsl2:
5007 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5008 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005009 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005010 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5011 "expected 6-bit signed immediate");
5012 case Match_UImm7_0:
5013 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5014 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005015 case Match_UImm7_N1:
5016 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5017 "expected immediate in range -1 .. 126");
5018 case Match_SImm7_Lsl2:
5019 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5020 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005021 case Match_UImm8_0:
5022 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5023 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005024 case Match_UImm10_0:
5025 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5026 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005027 case Match_SImm10_0:
5028 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5029 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005030 case Match_SImm11_0:
5031 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5032 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005033 case Match_UImm16:
5034 case Match_UImm16_Relaxed:
5035 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5036 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005037 case Match_SImm16:
5038 case Match_SImm16_Relaxed:
5039 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5040 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005041 case Match_SImm19_Lsl2:
5042 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5043 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005044 case Match_UImm20_0:
5045 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5046 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005047 case Match_UImm26_0:
5048 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5049 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005050 case Match_SImm32:
5051 case Match_SImm32_Relaxed:
5052 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5053 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005054 case Match_UImm32_Coerced:
5055 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5056 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005057 case Match_MemSImm9:
5058 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5059 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005060 case Match_MemSImm10:
5061 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5062 "expected memory with 10-bit signed offset");
5063 case Match_MemSImm10Lsl1:
5064 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5065 "expected memory with 11-bit signed offset and multiple of 2");
5066 case Match_MemSImm10Lsl2:
5067 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5068 "expected memory with 12-bit signed offset and multiple of 4");
5069 case Match_MemSImm10Lsl3:
5070 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5071 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005072 case Match_MemSImm11:
5073 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5074 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005075 case Match_MemSImm12:
5076 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5077 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005078 case Match_MemSImm16:
5079 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5080 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00005081 }
Craig Topper589ceee2015-01-03 08:16:34 +00005082
5083 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005084}
5085
Toma Tabacud9d344b2015-04-27 14:05:04 +00005086void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5087 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5088 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5089 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005090}
5091
Toma Tabacu81496c12015-05-20 08:54:45 +00005092void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5093 if (!AssemblerOptions.back()->isMacro())
5094 Warning(Loc, "macro instruction expanded into multiple instructions");
5095}
5096
Daniel Sandersef638fe2014-10-03 15:37:37 +00005097void
5098MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5099 SMRange Range, bool ShowColors) {
5100 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005101 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005102 ShowColors);
5103}
5104
Jack Carter1ac53222013-02-20 23:11:17 +00005105int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005106 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005107
Vladimir Medic4c299852013-11-06 11:27:05 +00005108 CC = StringSwitch<unsigned>(Name)
5109 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005110 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005111 .Case("a0", 4)
5112 .Case("a1", 5)
5113 .Case("a2", 6)
5114 .Case("a3", 7)
5115 .Case("v0", 2)
5116 .Case("v1", 3)
5117 .Case("s0", 16)
5118 .Case("s1", 17)
5119 .Case("s2", 18)
5120 .Case("s3", 19)
5121 .Case("s4", 20)
5122 .Case("s5", 21)
5123 .Case("s6", 22)
5124 .Case("s7", 23)
5125 .Case("k0", 26)
5126 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005127 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005128 .Case("sp", 29)
5129 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005130 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005131 .Case("ra", 31)
5132 .Case("t0", 8)
5133 .Case("t1", 9)
5134 .Case("t2", 10)
5135 .Case("t3", 11)
5136 .Case("t4", 12)
5137 .Case("t5", 13)
5138 .Case("t6", 14)
5139 .Case("t7", 15)
5140 .Case("t8", 24)
5141 .Case("t9", 25)
5142 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005143
Toma Tabacufda445c2014-09-15 15:33:01 +00005144 if (!(isABI_N32() || isABI_N64()))
5145 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005146
Daniel Sandersef638fe2014-10-03 15:37:37 +00005147 if (12 <= CC && CC <= 15) {
5148 // Name is one of t4-t7
5149 AsmToken RegTok = getLexer().peekTok();
5150 SMRange RegRange = RegTok.getLocRange();
5151
5152 StringRef FixedName = StringSwitch<StringRef>(Name)
5153 .Case("t4", "t0")
5154 .Case("t5", "t1")
5155 .Case("t6", "t2")
5156 .Case("t7", "t3")
5157 .Default("");
5158 assert(FixedName != "" && "Register name is not one of t4-t7.");
5159
5160 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5161 "Did you mean $" + FixedName + "?", RegRange);
5162 }
5163
Toma Tabacufda445c2014-09-15 15:33:01 +00005164 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5165 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5166 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5167 if (8 <= CC && CC <= 11)
5168 CC += 4;
5169
5170 if (CC == -1)
5171 CC = StringSwitch<unsigned>(Name)
5172 .Case("a4", 8)
5173 .Case("a5", 9)
5174 .Case("a6", 10)
5175 .Case("a7", 11)
5176 .Case("kt0", 26)
5177 .Case("kt1", 27)
5178 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005179
5180 return CC;
5181}
Jack Carterd0bd6422013-04-18 00:41:53 +00005182
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005183int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5184 int CC;
5185
5186 CC = StringSwitch<unsigned>(Name)
5187 .Case("hwr_cpunum", 0)
5188 .Case("hwr_synci_step", 1)
5189 .Case("hwr_cc", 2)
5190 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005191 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005192 .Default(-1);
5193
5194 return CC;
5195}
5196
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005197int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005198 if (Name[0] == 'f') {
5199 StringRef NumString = Name.substr(1);
5200 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005201 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005202 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005203 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005204 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005205 return IntVal;
5206 }
5207 return -1;
5208}
Jack Cartera63b16a2012-09-07 00:23:42 +00005209
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005210int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005211 if (Name.startswith("fcc")) {
5212 StringRef NumString = Name.substr(3);
5213 unsigned IntVal;
5214 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005215 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005216 if (IntVal > 7) // There are only 8 fcc registers.
5217 return -1;
5218 return IntVal;
5219 }
5220 return -1;
5221}
5222
5223int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005224 if (Name.startswith("ac")) {
5225 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005226 unsigned IntVal;
5227 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005228 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005229 if (IntVal > 3) // There are only 3 acc registers.
5230 return -1;
5231 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005232 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005233 return -1;
5234}
Jack Carterd0bd6422013-04-18 00:41:53 +00005235
Jack Carter5dc8ac92013-09-25 23:50:44 +00005236int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5237 unsigned IntVal;
5238
5239 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5240 return -1;
5241
5242 if (IntVal > 31)
5243 return -1;
5244
5245 return IntVal;
5246}
5247
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005248int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5249 int CC;
5250
5251 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005252 .Case("msair", 0)
5253 .Case("msacsr", 1)
5254 .Case("msaaccess", 2)
5255 .Case("msasave", 3)
5256 .Case("msamodify", 4)
5257 .Case("msarequest", 5)
5258 .Case("msamap", 6)
5259 .Case("msaunmap", 7)
5260 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005261
5262 return CC;
5263}
5264
Simon Dardis3aa8a902017-02-06 12:43:46 +00005265bool MipsAsmParser::canUseATReg() {
5266 return AssemblerOptions.back()->getATRegIndex() != 0;
5267}
5268
Toma Tabacu89a712b2015-04-15 10:48:56 +00005269unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005270 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005271 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005272 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005273 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005274 return 0;
5275 }
5276 unsigned AT = getReg(
5277 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005278 return AT;
5279}
Jack Carter0b744b32012-10-04 02:29:46 +00005280
Jack Carterd0bd6422013-04-18 00:41:53 +00005281unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005282 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005283}
5284
Toma Tabacu13964452014-09-04 13:23:44 +00005285bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005286 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005287 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005288
Jack Carter30a59822012-10-04 04:03:53 +00005289 // Check if the current operand has a custom associated parser, if so, try to
5290 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005291 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5292 if (ResTy == MatchOperand_Success)
5293 return false;
5294 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5295 // there was a match, but an error occurred, in which case, just return that
5296 // the operand parsing failed.
5297 if (ResTy == MatchOperand_ParseFail)
5298 return true;
5299
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005300 DEBUG(dbgs() << ".. Generic Parser\n");
5301
Jack Carterb4dbc172012-09-05 23:34:03 +00005302 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005303 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005304 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005305 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005306
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005307 // Almost all registers have been parsed by custom parsers. There is only
5308 // one exception to this. $zero (and it's alias $0) will reach this point
5309 // for div, divu, and similar instructions because it is not an operand
5310 // to the instruction definition but an explicit register. Special case
5311 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005312 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005313 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005314
Jack Carterd0bd6422013-04-18 00:41:53 +00005315 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005316 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005317 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005318 return true;
5319
Jack Carter873c7242013-01-12 01:03:14 +00005320 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005321 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005322 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005323 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005324 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005325
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005326 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005327 return false;
5328 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005329 default: {
5330 DEBUG(dbgs() << ".. generic integer expression\n");
5331
5332 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005333 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005334 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005335 return true;
5336
Jack Carter873c7242013-01-12 01:03:14 +00005337 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5338
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005339 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005340 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005341 }
Jack Carter0b744b32012-10-04 02:29:46 +00005342 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005343 return true;
5344}
5345
Jack Carterb5cf5902013-04-17 00:18:04 +00005346bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005347 switch (Expr->getKind()) {
5348 case MCExpr::Constant:
5349 return true;
5350 case MCExpr::SymbolRef:
5351 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
5352 case MCExpr::Binary:
5353 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
5354 if (!isEvaluated(BE->getLHS()))
5355 return false;
5356 return isEvaluated(BE->getRHS());
5357 }
5358 case MCExpr::Unary:
5359 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005360 case MCExpr::Target:
5361 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005362 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005363 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005364}
Jack Carterd0bd6422013-04-18 00:41:53 +00005365
Jack Carterb4dbc172012-09-05 23:34:03 +00005366bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5367 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005368 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005369 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005370 if (ResTy == MatchOperand_Success) {
5371 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005372 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005373 StartLoc = Operand.getStartLoc();
5374 EndLoc = Operand.getEndLoc();
5375
5376 // AFAIK, we only support numeric registers and named GPR's in CFI
5377 // directives.
5378 // Don't worry about eating tokens before failing. Using an unrecognised
5379 // register is a parse error.
5380 if (Operand.isGPRAsmReg()) {
5381 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005382 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005383 }
5384
5385 return (RegNo == (unsigned)-1);
5386 }
5387
5388 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005389 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005390}
5391
Jack Carterb5cf5902013-04-17 00:18:04 +00005392bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005393 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005394
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005395 if (isParenExpr)
5396 return getParser().parseParenExprOfDepth(0, Res, S);
5397 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005398}
5399
Alex Bradbury58eba092016-11-01 16:32:05 +00005400OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005401MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005402 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005403 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005404 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005405 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005406 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005407 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005408 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005409 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005410
Jack Carterb5cf5902013-04-17 00:18:04 +00005411 if (getLexer().getKind() == AsmToken::LParen) {
5412 Parser.Lex();
5413 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005414 }
5415
Jack Carterb5cf5902013-04-17 00:18:04 +00005416 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005417 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005418 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005419
Jack Carterd0bd6422013-04-18 00:41:53 +00005420 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005421 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005422 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005423 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005424 SMLoc E =
5425 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005426 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005427 return MatchOperand_Success;
5428 }
5429 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005430 SMLoc E =
5431 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005432
Jack Carterd0bd6422013-04-18 00:41:53 +00005433 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005434 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005435 auto Base = MipsOperand::createGPRReg(
5436 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005437 Operands.push_back(
5438 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005439 return MatchOperand_Success;
5440 }
Simon Dardis858915f2016-10-18 15:17:17 +00005441 MCBinaryExpr::Opcode Opcode;
5442 // GAS and LLVM treat comparison operators different. GAS will generate -1
5443 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5444 // highly unlikely to be found in a memory offset expression, we don't
5445 // handle them.
5446 switch (Tok.getKind()) {
5447 case AsmToken::Plus:
5448 Opcode = MCBinaryExpr::Add;
5449 Parser.Lex();
5450 break;
5451 case AsmToken::Minus:
5452 Opcode = MCBinaryExpr::Sub;
5453 Parser.Lex();
5454 break;
5455 case AsmToken::Star:
5456 Opcode = MCBinaryExpr::Mul;
5457 Parser.Lex();
5458 break;
5459 case AsmToken::Pipe:
5460 Opcode = MCBinaryExpr::Or;
5461 Parser.Lex();
5462 break;
5463 case AsmToken::Amp:
5464 Opcode = MCBinaryExpr::And;
5465 Parser.Lex();
5466 break;
5467 case AsmToken::LessLess:
5468 Opcode = MCBinaryExpr::Shl;
5469 Parser.Lex();
5470 break;
5471 case AsmToken::GreaterGreater:
5472 Opcode = MCBinaryExpr::LShr;
5473 Parser.Lex();
5474 break;
5475 case AsmToken::Caret:
5476 Opcode = MCBinaryExpr::Xor;
5477 Parser.Lex();
5478 break;
5479 case AsmToken::Slash:
5480 Opcode = MCBinaryExpr::Div;
5481 Parser.Lex();
5482 break;
5483 case AsmToken::Percent:
5484 Opcode = MCBinaryExpr::Mod;
5485 Parser.Lex();
5486 break;
5487 default:
5488 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5489 return MatchOperand_ParseFail;
5490 }
5491 const MCExpr * NextExpr;
5492 if (getParser().parseExpression(NextExpr))
5493 return MatchOperand_ParseFail;
5494 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005495 }
5496
Jack Carterd0bd6422013-04-18 00:41:53 +00005497 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005498 }
5499
Toma Tabacu13964452014-09-04 13:23:44 +00005500 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005501 if (Res != MatchOperand_Success)
5502 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005503
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005504 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005505 Error(Parser.getTok().getLoc(), "')' expected");
5506 return MatchOperand_ParseFail;
5507 }
5508
Jack Carter873c7242013-01-12 01:03:14 +00005509 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5510
Jack Carterd0bd6422013-04-18 00:41:53 +00005511 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005512
Craig Topper062a2ba2014-04-25 05:30:21 +00005513 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005514 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005515
Jack Carterd0bd6422013-04-18 00:41:53 +00005516 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005517 std::unique_ptr<MipsOperand> op(
5518 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005519 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005520 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005521 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005522 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005523 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5524 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005525 if (IdVal->evaluateAsAbsolute(Imm))
5526 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005527 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005528 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005529 getContext());
5530 }
5531
David Blaikie960ea3f2014-06-08 16:18:35 +00005532 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005533 return MatchOperand_Success;
5534}
5535
David Blaikie960ea3f2014-06-08 16:18:35 +00005536bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005537 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005538 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005539 if (Sym) {
5540 SMLoc S = Parser.getTok().getLoc();
5541 const MCExpr *Expr;
5542 if (Sym->isVariable())
5543 Expr = Sym->getVariableValue();
5544 else
5545 return false;
5546 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005547 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005548 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005549 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005550 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005551 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005552 if (ResTy == MatchOperand_Success) {
5553 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005554 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005555 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005556 llvm_unreachable("Should never ParseFail");
5557 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005558 }
Jack Carterd76b2372013-03-21 21:44:16 +00005559 }
5560 }
5561 return false;
5562}
Jack Carterd0bd6422013-04-18 00:41:53 +00005563
Alex Bradbury58eba092016-11-01 16:32:05 +00005564OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005565MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005566 StringRef Identifier,
5567 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005568 int Index = matchCPURegisterName(Identifier);
5569 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005570 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005571 Index, Identifier, getContext().getRegisterInfo(), S,
5572 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005573 return MatchOperand_Success;
5574 }
5575
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005576 Index = matchHWRegsRegisterName(Identifier);
5577 if (Index != -1) {
5578 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005579 Index, Identifier, getContext().getRegisterInfo(), S,
5580 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005581 return MatchOperand_Success;
5582 }
5583
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005584 Index = matchFPURegisterName(Identifier);
5585 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005586 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005587 Index, Identifier, getContext().getRegisterInfo(), S,
5588 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005589 return MatchOperand_Success;
5590 }
5591
5592 Index = matchFCCRegisterName(Identifier);
5593 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005594 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005595 Index, Identifier, getContext().getRegisterInfo(), S,
5596 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005597 return MatchOperand_Success;
5598 }
5599
5600 Index = matchACRegisterName(Identifier);
5601 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005602 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005603 Index, Identifier, getContext().getRegisterInfo(), S,
5604 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005605 return MatchOperand_Success;
5606 }
5607
5608 Index = matchMSA128RegisterName(Identifier);
5609 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005610 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005611 Index, Identifier, getContext().getRegisterInfo(), S,
5612 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005613 return MatchOperand_Success;
5614 }
5615
5616 Index = matchMSA128CtrlRegisterName(Identifier);
5617 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005618 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005619 Index, Identifier, getContext().getRegisterInfo(), S,
5620 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005621 return MatchOperand_Success;
5622 }
5623
5624 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005625}
5626
Alex Bradbury58eba092016-11-01 16:32:05 +00005627OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005628MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005629 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005630 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005631
5632 if (Token.is(AsmToken::Identifier)) {
5633 DEBUG(dbgs() << ".. identifier\n");
5634 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005635 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005636 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005637 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005638 } else if (Token.is(AsmToken::Integer)) {
5639 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005640 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005641 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5642 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005643 return MatchOperand_Success;
5644 }
5645
5646 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5647
5648 return MatchOperand_NoMatch;
5649}
5650
Alex Bradbury58eba092016-11-01 16:32:05 +00005651OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005652MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005653 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005654 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005655
5656 auto Token = Parser.getTok();
5657
5658 SMLoc S = Token.getLoc();
5659
5660 if (Token.isNot(AsmToken::Dollar)) {
5661 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5662 if (Token.is(AsmToken::Identifier)) {
5663 if (searchSymbolAlias(Operands))
5664 return MatchOperand_Success;
5665 }
5666 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5667 return MatchOperand_NoMatch;
5668 }
5669 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005670
Toma Tabacu13964452014-09-04 13:23:44 +00005671 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005672 if (ResTy == MatchOperand_Success) {
5673 Parser.Lex(); // $
5674 Parser.Lex(); // identifier
5675 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005676 return ResTy;
5677}
5678
Alex Bradbury58eba092016-11-01 16:32:05 +00005679OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005680MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005681 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005682 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005683
5684 SMLoc S = getLexer().getLoc();
5685
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005686 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005687 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005688 if (ResTy != MatchOperand_NoMatch)
5689 return ResTy;
5690
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005691 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005692 const MCExpr *Expr = nullptr;
5693 if (Parser.parseExpression(Expr)) {
5694 // We have no way of knowing if a symbol was consumed so we must ParseFail
5695 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005696 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005697 Operands.push_back(
5698 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005699 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005700}
5701
Alex Bradbury58eba092016-11-01 16:32:05 +00005702OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005703MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005704 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005705 const MCExpr *IdVal;
5706 // If the first token is '$' we may have register operand.
5707 if (Parser.getTok().is(AsmToken::Dollar))
5708 return MatchOperand_NoMatch;
5709 SMLoc S = Parser.getTok().getLoc();
5710 if (getParser().parseExpression(IdVal))
5711 return MatchOperand_ParseFail;
5712 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005713 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005714 int64_t Val = MCE->getValue();
5715 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5716 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005717 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005718 return MatchOperand_Success;
5719}
5720
Alex Bradbury58eba092016-11-01 16:32:05 +00005721OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005722MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5723 MCAsmParser &Parser = getParser();
5724 SmallVector<unsigned, 10> Regs;
5725 unsigned RegNo;
5726 unsigned PrevReg = Mips::NoRegister;
5727 bool RegRange = false;
5728 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5729
5730 if (Parser.getTok().isNot(AsmToken::Dollar))
5731 return MatchOperand_ParseFail;
5732
5733 SMLoc S = Parser.getTok().getLoc();
5734 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5735 SMLoc E = getLexer().getLoc();
5736 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5737 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5738 if (RegRange) {
5739 // Remove last register operand because registers from register range
5740 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005741 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5742 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005743 Regs.push_back(RegNo);
5744 } else {
5745 unsigned TmpReg = PrevReg + 1;
5746 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005747 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5748 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5749 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005750 Error(E, "invalid register operand");
5751 return MatchOperand_ParseFail;
5752 }
5753
5754 PrevReg = TmpReg;
5755 Regs.push_back(TmpReg++);
5756 }
5757 }
5758
5759 RegRange = false;
5760 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005761 if ((PrevReg == Mips::NoRegister) &&
5762 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5763 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005764 Error(E, "$16 or $31 expected");
5765 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005766 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5767 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5768 !isGP64bit()) ||
5769 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5770 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5771 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005772 Error(E, "invalid register operand");
5773 return MatchOperand_ParseFail;
5774 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005775 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5776 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5777 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005778 Error(E, "consecutive register numbers expected");
5779 return MatchOperand_ParseFail;
5780 }
5781
5782 Regs.push_back(RegNo);
5783 }
5784
5785 if (Parser.getTok().is(AsmToken::Minus))
5786 RegRange = true;
5787
5788 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5789 !Parser.getTok().isNot(AsmToken::Comma)) {
5790 Error(E, "',' or '-' expected");
5791 return MatchOperand_ParseFail;
5792 }
5793
5794 Lex(); // Consume comma or minus
5795 if (Parser.getTok().isNot(AsmToken::Dollar))
5796 break;
5797
5798 PrevReg = RegNo;
5799 }
5800
5801 SMLoc E = Parser.getTok().getLoc();
5802 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5803 parseMemOperand(Operands);
5804 return MatchOperand_Success;
5805}
5806
Alex Bradbury58eba092016-11-01 16:32:05 +00005807OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005808MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5809 MCAsmParser &Parser = getParser();
5810
5811 SMLoc S = Parser.getTok().getLoc();
5812 if (parseAnyRegister(Operands) != MatchOperand_Success)
5813 return MatchOperand_ParseFail;
5814
5815 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005816 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005817
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005818 Operands.pop_back();
5819 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005820 return MatchOperand_Success;
5821}
5822
Alex Bradbury58eba092016-11-01 16:32:05 +00005823OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005824MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5825 MCAsmParser &Parser = getParser();
5826 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5827 SmallVector<unsigned, 10> Regs;
5828
5829 if (Parser.getTok().isNot(AsmToken::Dollar))
5830 return MatchOperand_ParseFail;
5831
5832 SMLoc S = Parser.getTok().getLoc();
5833
5834 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5835 return MatchOperand_ParseFail;
5836
5837 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5838 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5839 Regs.push_back(RegNo);
5840
5841 SMLoc E = Parser.getTok().getLoc();
5842 if (Parser.getTok().isNot(AsmToken::Comma)) {
5843 Error(E, "',' expected");
5844 return MatchOperand_ParseFail;
5845 }
5846
5847 // Remove comma.
5848 Parser.Lex();
5849
5850 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5851 return MatchOperand_ParseFail;
5852
5853 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5854 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5855 Regs.push_back(RegNo);
5856
5857 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5858
5859 return MatchOperand_Success;
5860}
5861
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005862/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5863/// either this.
5864/// ::= '(', register, ')'
5865/// handle it before we iterate so we don't get tripped up by the lack of
5866/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005867bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005868 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005869 if (getLexer().is(AsmToken::LParen)) {
5870 Operands.push_back(
5871 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5872 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005873 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005874 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005875 return Error(Loc, "unexpected token in argument list");
5876 }
5877 if (Parser.getTok().isNot(AsmToken::RParen)) {
5878 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005879 return Error(Loc, "unexpected token, expected ')'");
5880 }
5881 Operands.push_back(
5882 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5883 Parser.Lex();
5884 }
5885 return false;
5886}
5887
5888/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5889/// either one of these.
5890/// ::= '[', register, ']'
5891/// ::= '[', integer, ']'
5892/// handle it before we iterate so we don't get tripped up by the lack of
5893/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005894bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005895 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005896 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005897 if (getLexer().is(AsmToken::LBrac)) {
5898 Operands.push_back(
5899 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5900 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005901 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005902 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005903 return Error(Loc, "unexpected token in argument list");
5904 }
5905 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5906 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005907 return Error(Loc, "unexpected token, expected ']'");
5908 }
5909 Operands.push_back(
5910 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5911 Parser.Lex();
5912 }
5913 return false;
5914}
5915
David Blaikie960ea3f2014-06-08 16:18:35 +00005916bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5917 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005918 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005919 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005920
5921 // We have reached first instruction, module directive are now forbidden.
5922 getTargetStreamer().forbidModuleDirective();
5923
Vladimir Medic74593e62013-07-17 15:00:42 +00005924 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005925 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005926 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005927 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005928 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005929 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005930
5931 // Read the remaining operands.
5932 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5933 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005934 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005935 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005936 return Error(Loc, "unexpected token in argument list");
5937 }
Toma Tabacu13964452014-09-04 13:23:44 +00005938 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005939 return true;
5940 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005941
Jack Carterd0bd6422013-04-18 00:41:53 +00005942 while (getLexer().is(AsmToken::Comma)) {
5943 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005944 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005945 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005946 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005947 return Error(Loc, "unexpected token in argument list");
5948 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005949 // Parse bracket and parenthesis suffixes before we iterate
5950 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005951 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005952 return true;
5953 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005954 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005955 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005956 }
5957 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005958 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5959 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005960 return Error(Loc, "unexpected token in argument list");
5961 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005962 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005963 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005964}
5965
Nirav Dave996fc132016-05-05 14:15:46 +00005966// FIXME: Given that these have the same name, these should both be
5967// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005968bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005969 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005970 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005971}
5972
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005973bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005974 return Error(Loc, ErrorMsg);
5975}
5976
Jack Carter0b744b32012-10-04 02:29:46 +00005977bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005978 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005979 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005980
5981 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005982 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005983
5984 Parser.Lex(); // Eat "noat".
5985
Jack Carterd0bd6422013-04-18 00:41:53 +00005986 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005987 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005988 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005989 return false;
5990 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005991
5992 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005993 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005994 return false;
5995}
Jack Carterd0bd6422013-04-18 00:41:53 +00005996
Jack Carter0b744b32012-10-04 02:29:46 +00005997bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005998 // Line can be: ".set at", which sets $at to $1
5999 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006000 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006001 Parser.Lex(); // Eat "at".
6002
Jack Carter0b744b32012-10-04 02:29:46 +00006003 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006004 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006005 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006006
6007 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006008 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006009 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006010 }
6011
6012 if (getLexer().isNot(AsmToken::Equal)) {
6013 reportParseError("unexpected token, expected equals sign");
6014 return false;
6015 }
6016 Parser.Lex(); // Eat "=".
6017
6018 if (getLexer().isNot(AsmToken::Dollar)) {
6019 if (getLexer().is(AsmToken::EndOfStatement)) {
6020 reportParseError("no register specified");
6021 return false;
6022 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006023 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006024 return false;
6025 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006026 }
6027 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006028
Toma Tabacu16a74492015-02-13 10:30:57 +00006029 // Find out what "reg" is.
6030 unsigned AtRegNo;
6031 const AsmToken &Reg = Parser.getTok();
6032 if (Reg.is(AsmToken::Identifier)) {
6033 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6034 } else if (Reg.is(AsmToken::Integer)) {
6035 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006036 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006037 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006038 return false;
6039 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006040
6041 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006042 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006043 reportParseError("invalid register");
6044 return false;
6045 }
6046 Parser.Lex(); // Eat "reg".
6047
6048 // If this is not the end of the statement, report an error.
6049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6050 reportParseError("unexpected token, expected end of statement");
6051 return false;
6052 }
6053
6054 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6055
6056 Parser.Lex(); // Consume the EndOfStatement.
6057 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006058}
6059
6060bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006061 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006062 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006063 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006064 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006065 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006066 return false;
6067 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006068 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006069 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006070 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006071 return false;
6072}
6073
6074bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006075 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006076 Parser.Lex();
6077 // If this is not the end of the statement, report an error.
6078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006079 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006080 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006081 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006082 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006083 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006084 Parser.Lex(); // Consume the EndOfStatement.
6085 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006086}
6087
6088bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006089 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006090 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006091 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006092 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006093 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006094 return false;
6095 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006096 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006097 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006098 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006099 return false;
6100}
6101
6102bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006103 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006104 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006105 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006106 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006107 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006108 return false;
6109 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006110 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006111 reportParseError("`noreorder' must be set before `nomacro'");
6112 return false;
6113 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006114 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006115 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006116 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006117 return false;
6118}
Jack Carterd76b2372013-03-21 21:44:16 +00006119
Daniel Sanders44934432014-08-07 12:03:36 +00006120bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006121 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006122 Parser.Lex();
6123
6124 // If this is not the end of the statement, report an error.
6125 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006126 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006127
6128 setFeatureBits(Mips::FeatureMSA, "msa");
6129 getTargetStreamer().emitDirectiveSetMsa();
6130 return false;
6131}
6132
6133bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006134 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006135 Parser.Lex();
6136
6137 // If this is not the end of the statement, report an error.
6138 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006139 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006140
6141 clearFeatureBits(Mips::FeatureMSA, "msa");
6142 getTargetStreamer().emitDirectiveSetNoMsa();
6143 return false;
6144}
6145
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006146bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006147 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006148 Parser.Lex(); // Eat "nodsp".
6149
6150 // If this is not the end of the statement, report an error.
6151 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6152 reportParseError("unexpected token, expected end of statement");
6153 return false;
6154 }
6155
6156 clearFeatureBits(Mips::FeatureDSP, "dsp");
6157 getTargetStreamer().emitDirectiveSetNoDsp();
6158 return false;
6159}
6160
Toma Tabacucc2502d2014-11-04 17:18:07 +00006161bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006162 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006163 Parser.Lex(); // Eat "mips16".
6164
Jack Carter39536722014-01-22 23:08:42 +00006165 // If this is not the end of the statement, report an error.
6166 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006167 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006168 return false;
6169 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006170
6171 setFeatureBits(Mips::FeatureMips16, "mips16");
6172 getTargetStreamer().emitDirectiveSetMips16();
6173 Parser.Lex(); // Consume the EndOfStatement.
6174 return false;
6175}
6176
6177bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006178 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006179 Parser.Lex(); // Eat "nomips16".
6180
6181 // If this is not the end of the statement, report an error.
6182 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6183 reportParseError("unexpected token, expected end of statement");
6184 return false;
6185 }
6186
6187 clearFeatureBits(Mips::FeatureMips16, "mips16");
6188 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006189 Parser.Lex(); // Consume the EndOfStatement.
6190 return false;
6191}
6192
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006193bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006194 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006195 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006196 // Line can be: .set fp=32
6197 // .set fp=xx
6198 // .set fp=64
6199 Parser.Lex(); // Eat fp token
6200 AsmToken Tok = Parser.getTok();
6201 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006202 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006203 return false;
6204 }
6205 Parser.Lex(); // Eat '=' token.
6206 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006207
6208 if (!parseFpABIValue(FpAbiVal, ".set"))
6209 return false;
6210
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006211 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006212 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006213 return false;
6214 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006215 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006216 Parser.Lex(); // Consume the EndOfStatement.
6217 return false;
6218}
6219
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006220bool MipsAsmParser::parseSetOddSPRegDirective() {
6221 MCAsmParser &Parser = getParser();
6222
6223 Parser.Lex(); // Eat "oddspreg".
6224 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6225 reportParseError("unexpected token, expected end of statement");
6226 return false;
6227 }
6228
6229 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6230 getTargetStreamer().emitDirectiveSetOddSPReg();
6231 return false;
6232}
6233
6234bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6235 MCAsmParser &Parser = getParser();
6236
6237 Parser.Lex(); // Eat "nooddspreg".
6238 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6239 reportParseError("unexpected token, expected end of statement");
6240 return false;
6241 }
6242
6243 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6244 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6245 return false;
6246}
6247
Toma Tabacu9db22db2014-09-09 10:15:38 +00006248bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006249 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006250 SMLoc Loc = getLexer().getLoc();
6251
6252 Parser.Lex();
6253 if (getLexer().isNot(AsmToken::EndOfStatement))
6254 return reportParseError("unexpected token, expected end of statement");
6255
6256 // Always keep an element on the options "stack" to prevent the user
6257 // from changing the initial options. This is how we remember them.
6258 if (AssemblerOptions.size() == 2)
6259 return reportParseError(Loc, ".set pop with no .set push");
6260
Akira Hatanakab11ef082015-11-14 06:35:56 +00006261 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006262 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006263 setAvailableFeatures(
6264 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6265 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006266
6267 getTargetStreamer().emitDirectiveSetPop();
6268 return false;
6269}
6270
6271bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006272 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006273 Parser.Lex();
6274 if (getLexer().isNot(AsmToken::EndOfStatement))
6275 return reportParseError("unexpected token, expected end of statement");
6276
6277 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006278 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006279 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006280
6281 getTargetStreamer().emitDirectiveSetPush();
6282 return false;
6283}
6284
Toma Tabacu29696502015-06-02 09:48:04 +00006285bool MipsAsmParser::parseSetSoftFloatDirective() {
6286 MCAsmParser &Parser = getParser();
6287 Parser.Lex();
6288 if (getLexer().isNot(AsmToken::EndOfStatement))
6289 return reportParseError("unexpected token, expected end of statement");
6290
6291 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6292 getTargetStreamer().emitDirectiveSetSoftFloat();
6293 return false;
6294}
6295
6296bool MipsAsmParser::parseSetHardFloatDirective() {
6297 MCAsmParser &Parser = getParser();
6298 Parser.Lex();
6299 if (getLexer().isNot(AsmToken::EndOfStatement))
6300 return reportParseError("unexpected token, expected end of statement");
6301
6302 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6303 getTargetStreamer().emitDirectiveSetHardFloat();
6304 return false;
6305}
6306
Jack Carterd76b2372013-03-21 21:44:16 +00006307bool MipsAsmParser::parseSetAssignment() {
6308 StringRef Name;
6309 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006310 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006311
6312 if (Parser.parseIdentifier(Name))
6313 reportParseError("expected identifier after .set");
6314
6315 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006316 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006317 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006318
Jack Carter3b2c96e2014-01-22 23:31:38 +00006319 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006320 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006321
Jim Grosbach6f482002015-05-18 18:43:14 +00006322 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006323 Sym->setVariableValue(Value);
6324
6325 return false;
6326}
Jack Carterd0bd6422013-04-18 00:41:53 +00006327
Toma Tabacu26647792014-09-09 12:52:14 +00006328bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006329 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006330 Parser.Lex();
6331 if (getLexer().isNot(AsmToken::EndOfStatement))
6332 return reportParseError("unexpected token, expected end of statement");
6333
6334 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006335 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006336 setAvailableFeatures(
6337 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6338 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006339 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6340
6341 getTargetStreamer().emitDirectiveSetMips0();
6342 return false;
6343}
6344
Toma Tabacu85618b32014-08-19 14:22:52 +00006345bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006346 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006347 Parser.Lex();
6348 if (getLexer().isNot(AsmToken::Equal))
6349 return reportParseError("unexpected token, expected equals sign");
6350
6351 Parser.Lex();
6352 StringRef Arch;
6353 if (Parser.parseIdentifier(Arch))
6354 return reportParseError("expected arch identifier");
6355
6356 StringRef ArchFeatureName =
6357 StringSwitch<StringRef>(Arch)
6358 .Case("mips1", "mips1")
6359 .Case("mips2", "mips2")
6360 .Case("mips3", "mips3")
6361 .Case("mips4", "mips4")
6362 .Case("mips5", "mips5")
6363 .Case("mips32", "mips32")
6364 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006365 .Case("mips32r3", "mips32r3")
6366 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006367 .Case("mips32r6", "mips32r6")
6368 .Case("mips64", "mips64")
6369 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006370 .Case("mips64r3", "mips64r3")
6371 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006372 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006373 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006374 .Case("r4000", "mips3") // This is an implementation of Mips3.
6375 .Default("");
6376
6377 if (ArchFeatureName.empty())
6378 return reportParseError("unsupported architecture");
6379
6380 selectArch(ArchFeatureName);
6381 getTargetStreamer().emitDirectiveSetArch(Arch);
6382 return false;
6383}
6384
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006385bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006386 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006387 Parser.Lex();
6388 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006389 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006390
Matheus Almeida2852af82014-04-22 10:15:54 +00006391 switch (Feature) {
6392 default:
6393 llvm_unreachable("Unimplemented feature");
6394 case Mips::FeatureDSP:
6395 setFeatureBits(Mips::FeatureDSP, "dsp");
6396 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006397 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006398 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006399 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006400 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006401 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006402 case Mips::FeatureMips1:
6403 selectArch("mips1");
6404 getTargetStreamer().emitDirectiveSetMips1();
6405 break;
6406 case Mips::FeatureMips2:
6407 selectArch("mips2");
6408 getTargetStreamer().emitDirectiveSetMips2();
6409 break;
6410 case Mips::FeatureMips3:
6411 selectArch("mips3");
6412 getTargetStreamer().emitDirectiveSetMips3();
6413 break;
6414 case Mips::FeatureMips4:
6415 selectArch("mips4");
6416 getTargetStreamer().emitDirectiveSetMips4();
6417 break;
6418 case Mips::FeatureMips5:
6419 selectArch("mips5");
6420 getTargetStreamer().emitDirectiveSetMips5();
6421 break;
6422 case Mips::FeatureMips32:
6423 selectArch("mips32");
6424 getTargetStreamer().emitDirectiveSetMips32();
6425 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006426 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006427 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006428 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006429 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006430 case Mips::FeatureMips32r3:
6431 selectArch("mips32r3");
6432 getTargetStreamer().emitDirectiveSetMips32R3();
6433 break;
6434 case Mips::FeatureMips32r5:
6435 selectArch("mips32r5");
6436 getTargetStreamer().emitDirectiveSetMips32R5();
6437 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006438 case Mips::FeatureMips32r6:
6439 selectArch("mips32r6");
6440 getTargetStreamer().emitDirectiveSetMips32R6();
6441 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006442 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006443 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006444 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006445 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006446 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006447 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006448 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006449 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006450 case Mips::FeatureMips64r3:
6451 selectArch("mips64r3");
6452 getTargetStreamer().emitDirectiveSetMips64R3();
6453 break;
6454 case Mips::FeatureMips64r5:
6455 selectArch("mips64r5");
6456 getTargetStreamer().emitDirectiveSetMips64R5();
6457 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006458 case Mips::FeatureMips64r6:
6459 selectArch("mips64r6");
6460 getTargetStreamer().emitDirectiveSetMips64R6();
6461 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006462 }
6463 return false;
6464}
6465
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006466bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006467 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006468 if (getLexer().isNot(AsmToken::Comma)) {
6469 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006470 return Error(Loc, ErrorStr);
6471 }
6472
Matheus Almeida2852af82014-04-22 10:15:54 +00006473 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006474 return true;
6475}
6476
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006477// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6478// In this class, it is only used for .cprestore.
6479// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6480// MipsTargetELFStreamer and MipsAsmParser.
6481bool MipsAsmParser::isPicAndNotNxxAbi() {
6482 return inPicMode() && !(isABI_N32() || isABI_N64());
6483}
6484
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006485bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006486 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006487 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006488
Toma Tabacudde4c462014-11-06 10:02:45 +00006489 if (inMips16Mode()) {
6490 reportParseError(".cpload is not supported in Mips16 mode");
6491 return false;
6492 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006493
David Blaikie960ea3f2014-06-08 16:18:35 +00006494 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006495 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006496 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6497 reportParseError("expected register containing function address");
6498 return false;
6499 }
6500
David Blaikie960ea3f2014-06-08 16:18:35 +00006501 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6502 if (!RegOpnd.isGPRAsmReg()) {
6503 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006504 return false;
6505 }
6506
Toma Tabacudde4c462014-11-06 10:02:45 +00006507 // If this is not the end of the statement, report an error.
6508 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6509 reportParseError("unexpected token, expected end of statement");
6510 return false;
6511 }
6512
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006513 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006514 return false;
6515}
6516
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006517bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6518 MCAsmParser &Parser = getParser();
6519
6520 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6521 // is used in non-PIC mode.
6522
6523 if (inMips16Mode()) {
6524 reportParseError(".cprestore is not supported in Mips16 mode");
6525 return false;
6526 }
6527
6528 // Get the stack offset value.
6529 const MCExpr *StackOffset;
6530 int64_t StackOffsetVal;
6531 if (Parser.parseExpression(StackOffset)) {
6532 reportParseError("expected stack offset value");
6533 return false;
6534 }
6535
6536 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6537 reportParseError("stack offset is not an absolute expression");
6538 return false;
6539 }
6540
6541 if (StackOffsetVal < 0) {
6542 Warning(Loc, ".cprestore with negative stack offset has no effect");
6543 IsCpRestoreSet = false;
6544 } else {
6545 IsCpRestoreSet = true;
6546 CpRestoreOffset = StackOffsetVal;
6547 }
6548
6549 // If this is not the end of the statement, report an error.
6550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6551 reportParseError("unexpected token, expected end of statement");
6552 return false;
6553 }
6554
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006555 if (!getTargetStreamer().emitDirectiveCpRestore(
6556 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006557 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006558 Parser.Lex(); // Consume the EndOfStatement.
6559 return false;
6560}
6561
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006562bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006563 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006564 unsigned FuncReg;
6565 unsigned Save;
6566 bool SaveIsReg = true;
6567
Matheus Almeida7e815762014-06-18 13:08:59 +00006568 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006569 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006570 if (ResTy == MatchOperand_NoMatch) {
6571 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006572 return false;
6573 }
6574
6575 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6576 if (!FuncRegOpnd.isGPRAsmReg()) {
6577 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006578 return false;
6579 }
6580
6581 FuncReg = FuncRegOpnd.getGPR32Reg();
6582 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006583
Toma Tabacu65f10572014-09-16 15:00:52 +00006584 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006585 return true;
6586
Toma Tabacu13964452014-09-04 13:23:44 +00006587 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006588 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006589 const MCExpr *OffsetExpr;
6590 int64_t OffsetVal;
6591 SMLoc ExprLoc = getLexer().getLoc();
6592
6593 if (Parser.parseExpression(OffsetExpr) ||
6594 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6595 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006596 return false;
6597 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006598
6599 Save = OffsetVal;
6600 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006601 } else {
6602 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6603 if (!SaveOpnd.isGPRAsmReg()) {
6604 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006605 return false;
6606 }
6607 Save = SaveOpnd.getGPR32Reg();
6608 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006609
Toma Tabacu65f10572014-09-16 15:00:52 +00006610 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006611 return true;
6612
Toma Tabacu8874eac2015-02-18 13:46:53 +00006613 const MCExpr *Expr;
6614 if (Parser.parseExpression(Expr)) {
6615 reportParseError("expected expression");
6616 return false;
6617 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006618
Toma Tabacu8874eac2015-02-18 13:46:53 +00006619 if (Expr->getKind() != MCExpr::SymbolRef) {
6620 reportParseError("expected symbol");
6621 return false;
6622 }
6623 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6624
Daniel Sandersf173dda2015-09-22 10:50:09 +00006625 CpSaveLocation = Save;
6626 CpSaveLocationIsRegister = SaveIsReg;
6627
Toma Tabacu8874eac2015-02-18 13:46:53 +00006628 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6629 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006630 return false;
6631}
6632
Daniel Sandersf173dda2015-09-22 10:50:09 +00006633bool MipsAsmParser::parseDirectiveCPReturn() {
6634 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6635 CpSaveLocationIsRegister);
6636 return false;
6637}
6638
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006639bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006640 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006641 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6642 const AsmToken &Tok = Parser.getTok();
6643
6644 if (Tok.getString() == "2008") {
6645 Parser.Lex();
6646 getTargetStreamer().emitDirectiveNaN2008();
6647 return false;
6648 } else if (Tok.getString() == "legacy") {
6649 Parser.Lex();
6650 getTargetStreamer().emitDirectiveNaNLegacy();
6651 return false;
6652 }
6653 }
6654 // If we don't recognize the option passed to the .nan
6655 // directive (e.g. no option or unknown option), emit an error.
6656 reportParseError("invalid option in .nan directive");
6657 return false;
6658}
6659
Jack Carter0b744b32012-10-04 02:29:46 +00006660bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006661 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006662 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006663 const AsmToken &Tok = Parser.getTok();
6664
6665 if (Tok.getString() == "noat") {
6666 return parseSetNoAtDirective();
6667 } else if (Tok.getString() == "at") {
6668 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006669 } else if (Tok.getString() == "arch") {
6670 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006671 } else if (Tok.getString() == "bopt") {
6672 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6673 getParser().Lex();
6674 return false;
6675 } else if (Tok.getString() == "nobopt") {
6676 // We're already running in nobopt mode, so nothing to do.
6677 getParser().Lex();
6678 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006679 } else if (Tok.getString() == "fp") {
6680 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006681 } else if (Tok.getString() == "oddspreg") {
6682 return parseSetOddSPRegDirective();
6683 } else if (Tok.getString() == "nooddspreg") {
6684 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006685 } else if (Tok.getString() == "pop") {
6686 return parseSetPopDirective();
6687 } else if (Tok.getString() == "push") {
6688 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006689 } else if (Tok.getString() == "reorder") {
6690 return parseSetReorderDirective();
6691 } else if (Tok.getString() == "noreorder") {
6692 return parseSetNoReorderDirective();
6693 } else if (Tok.getString() == "macro") {
6694 return parseSetMacroDirective();
6695 } else if (Tok.getString() == "nomacro") {
6696 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006697 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006698 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006699 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006700 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006701 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006702 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006703 getTargetStreamer().emitDirectiveSetNoMicroMips();
6704 Parser.eatToEndOfStatement();
6705 return false;
6706 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006707 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006708 } else if (Tok.getString() == "mips0") {
6709 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006710 } else if (Tok.getString() == "mips1") {
6711 return parseSetFeature(Mips::FeatureMips1);
6712 } else if (Tok.getString() == "mips2") {
6713 return parseSetFeature(Mips::FeatureMips2);
6714 } else if (Tok.getString() == "mips3") {
6715 return parseSetFeature(Mips::FeatureMips3);
6716 } else if (Tok.getString() == "mips4") {
6717 return parseSetFeature(Mips::FeatureMips4);
6718 } else if (Tok.getString() == "mips5") {
6719 return parseSetFeature(Mips::FeatureMips5);
6720 } else if (Tok.getString() == "mips32") {
6721 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006722 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006723 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006724 } else if (Tok.getString() == "mips32r3") {
6725 return parseSetFeature(Mips::FeatureMips32r3);
6726 } else if (Tok.getString() == "mips32r5") {
6727 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006728 } else if (Tok.getString() == "mips32r6") {
6729 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006730 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006731 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006732 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006733 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006734 } else if (Tok.getString() == "mips64r3") {
6735 return parseSetFeature(Mips::FeatureMips64r3);
6736 } else if (Tok.getString() == "mips64r5") {
6737 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006738 } else if (Tok.getString() == "mips64r6") {
6739 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006740 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006741 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006742 } else if (Tok.getString() == "nodsp") {
6743 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006744 } else if (Tok.getString() == "msa") {
6745 return parseSetMsaDirective();
6746 } else if (Tok.getString() == "nomsa") {
6747 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006748 } else if (Tok.getString() == "softfloat") {
6749 return parseSetSoftFloatDirective();
6750 } else if (Tok.getString() == "hardfloat") {
6751 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006752 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006753 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006754 parseSetAssignment();
6755 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006756 }
Jack Carter07c818d2013-01-25 01:31:34 +00006757
Jack Carter0b744b32012-10-04 02:29:46 +00006758 return true;
6759}
6760
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006761/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006762/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006763bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006764 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006765 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006766 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006767 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006768 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006769 return true;
6770
6771 getParser().getStreamer().EmitValue(Value, Size);
6772
6773 if (getLexer().is(AsmToken::EndOfStatement))
6774 break;
6775
Jack Carter07c818d2013-01-25 01:31:34 +00006776 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006777 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006778 Parser.Lex();
6779 }
6780 }
6781
6782 Parser.Lex();
6783 return false;
6784}
6785
Vladimir Medic4c299852013-11-06 11:27:05 +00006786/// parseDirectiveGpWord
6787/// ::= .gpword local_sym
6788bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006789 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006790 const MCExpr *Value;
6791 // EmitGPRel32Value requires an expression, so we are using base class
6792 // method to evaluate the expression.
6793 if (getParser().parseExpression(Value))
6794 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006795 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006796
Vladimir Medice10c1122013-11-13 13:18:04 +00006797 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006798 return Error(getLexer().getLoc(),
6799 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006800 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006801 return false;
6802}
6803
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006804/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006805/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006806bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006807 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006808 const MCExpr *Value;
6809 // EmitGPRel64Value requires an expression, so we are using base class
6810 // method to evaluate the expression.
6811 if (getParser().parseExpression(Value))
6812 return true;
6813 getParser().getStreamer().EmitGPRel64Value(Value);
6814
6815 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006816 return Error(getLexer().getLoc(),
6817 "unexpected token, expected end of statement");
6818 Parser.Lex(); // Eat EndOfStatement token.
6819 return false;
6820}
6821
6822/// parseDirectiveDtpRelWord
6823/// ::= .dtprelword tls_sym
6824bool MipsAsmParser::parseDirectiveDtpRelWord() {
6825 MCAsmParser &Parser = getParser();
6826 const MCExpr *Value;
6827 // EmitDTPRel32Value requires an expression, so we are using base class
6828 // method to evaluate the expression.
6829 if (getParser().parseExpression(Value))
6830 return true;
6831 getParser().getStreamer().EmitDTPRel32Value(Value);
6832
6833 if (getLexer().isNot(AsmToken::EndOfStatement))
6834 return Error(getLexer().getLoc(),
6835 "unexpected token, expected end of statement");
6836 Parser.Lex(); // Eat EndOfStatement token.
6837 return false;
6838}
6839
6840/// parseDirectiveDtpRelDWord
6841/// ::= .dtpreldword tls_sym
6842bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6843 MCAsmParser &Parser = getParser();
6844 const MCExpr *Value;
6845 // EmitDTPRel64Value requires an expression, so we are using base class
6846 // method to evaluate the expression.
6847 if (getParser().parseExpression(Value))
6848 return true;
6849 getParser().getStreamer().EmitDTPRel64Value(Value);
6850
6851 if (getLexer().isNot(AsmToken::EndOfStatement))
6852 return Error(getLexer().getLoc(),
6853 "unexpected token, expected end of statement");
6854 Parser.Lex(); // Eat EndOfStatement token.
6855 return false;
6856}
6857
6858/// parseDirectiveTpRelWord
6859/// ::= .tprelword tls_sym
6860bool MipsAsmParser::parseDirectiveTpRelWord() {
6861 MCAsmParser &Parser = getParser();
6862 const MCExpr *Value;
6863 // EmitTPRel32Value requires an expression, so we are using base class
6864 // method to evaluate the expression.
6865 if (getParser().parseExpression(Value))
6866 return true;
6867 getParser().getStreamer().EmitTPRel32Value(Value);
6868
6869 if (getLexer().isNot(AsmToken::EndOfStatement))
6870 return Error(getLexer().getLoc(),
6871 "unexpected token, expected end of statement");
6872 Parser.Lex(); // Eat EndOfStatement token.
6873 return false;
6874}
6875
6876/// parseDirectiveTpRelDWord
6877/// ::= .tpreldword tls_sym
6878bool MipsAsmParser::parseDirectiveTpRelDWord() {
6879 MCAsmParser &Parser = getParser();
6880 const MCExpr *Value;
6881 // EmitTPRel64Value requires an expression, so we are using base class
6882 // method to evaluate the expression.
6883 if (getParser().parseExpression(Value))
6884 return true;
6885 getParser().getStreamer().EmitTPRel64Value(Value);
6886
6887 if (getLexer().isNot(AsmToken::EndOfStatement))
6888 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006889 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006890 Parser.Lex(); // Eat EndOfStatement token.
6891 return false;
6892}
6893
Jack Carter0cd3c192014-01-06 23:27:31 +00006894bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006895 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006896 // Get the option token.
6897 AsmToken Tok = Parser.getTok();
6898 // At the moment only identifiers are supported.
6899 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006900 return Error(Parser.getTok().getLoc(),
6901 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006902 }
6903
6904 StringRef Option = Tok.getIdentifier();
6905
6906 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006907 // MipsAsmParser needs to know if the current PIC mode changes.
6908 IsPicEnabled = false;
6909
Jack Carter0cd3c192014-01-06 23:27:31 +00006910 getTargetStreamer().emitDirectiveOptionPic0();
6911 Parser.Lex();
6912 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006913 return Error(Parser.getTok().getLoc(),
6914 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006915 }
6916 return false;
6917 }
6918
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006919 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006920 // MipsAsmParser needs to know if the current PIC mode changes.
6921 IsPicEnabled = true;
6922
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006923 getTargetStreamer().emitDirectiveOptionPic2();
6924 Parser.Lex();
6925 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006926 return Error(Parser.getTok().getLoc(),
6927 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006928 }
6929 return false;
6930 }
6931
Jack Carter0cd3c192014-01-06 23:27:31 +00006932 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006933 Warning(Parser.getTok().getLoc(),
6934 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006935 Parser.eatToEndOfStatement();
6936 return false;
6937}
6938
Toma Tabacu9ca50962015-04-16 09:53:47 +00006939/// parseInsnDirective
6940/// ::= .insn
6941bool MipsAsmParser::parseInsnDirective() {
6942 // If this is not the end of the statement, report an error.
6943 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6944 reportParseError("unexpected token, expected end of statement");
6945 return false;
6946 }
6947
6948 // The actual label marking happens in
6949 // MipsELFStreamer::createPendingLabelRelocs().
6950 getTargetStreamer().emitDirectiveInsn();
6951
6952 getParser().Lex(); // Eat EndOfStatement token.
6953 return false;
6954}
6955
Simon Dardis1c73fcc2017-06-22 10:41:51 +00006956/// parseRSectionDirective
6957/// ::= .rdata
6958bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
6959 // If this is not the end of the statement, report an error.
6960 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6961 reportParseError("unexpected token, expected end of statement");
6962 return false;
6963 }
6964
6965 MCSection *ELFSection = getContext().getELFSection(
6966 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
6967 getParser().getStreamer().SwitchSection(ELFSection);
6968
6969 getParser().Lex(); // Eat EndOfStatement token.
6970 return false;
6971}
6972
Simon Atanasyanbe186202016-02-11 06:45:54 +00006973/// parseSSectionDirective
6974/// ::= .sbss
6975/// ::= .sdata
6976bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6977 // If this is not the end of the statement, report an error.
6978 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6979 reportParseError("unexpected token, expected end of statement");
6980 return false;
6981 }
6982
6983 MCSection *ELFSection = getContext().getELFSection(
6984 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6985 getParser().getStreamer().SwitchSection(ELFSection);
6986
6987 getParser().Lex(); // Eat EndOfStatement token.
6988 return false;
6989}
6990
Daniel Sanders7e527422014-07-10 13:38:23 +00006991/// parseDirectiveModule
6992/// ::= .module oddspreg
6993/// ::= .module nooddspreg
6994/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006995/// ::= .module softfloat
6996/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006997bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006998 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006999 MCAsmLexer &Lexer = getLexer();
7000 SMLoc L = Lexer.getLoc();
7001
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007002 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007003 // TODO : get a better message.
7004 reportParseError(".module directive must appear before any code");
7005 return false;
7006 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007007
Toma Tabacuc405c822015-01-23 10:40:19 +00007008 StringRef Option;
7009 if (Parser.parseIdentifier(Option)) {
7010 reportParseError("expected .module option identifier");
7011 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007012 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007013
Toma Tabacuc405c822015-01-23 10:40:19 +00007014 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007015 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007016
Toma Tabacu3c499582015-06-25 10:56:57 +00007017 // Synchronize the abiflags information with the FeatureBits information we
7018 // changed above.
7019 getTargetStreamer().updateABIInfo(*this);
7020
7021 // If printing assembly, use the recently updated abiflags information.
7022 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7023 // emitted at the end).
7024 getTargetStreamer().emitDirectiveModuleOddSPReg();
7025
Toma Tabacuc405c822015-01-23 10:40:19 +00007026 // If this is not the end of the statement, report an error.
7027 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7028 reportParseError("unexpected token, expected end of statement");
7029 return false;
7030 }
7031
7032 return false; // parseDirectiveModule has finished successfully.
7033 } else if (Option == "nooddspreg") {
7034 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007035 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007036 }
7037
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007038 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007039
Toma Tabacu3c499582015-06-25 10:56:57 +00007040 // Synchronize the abiflags information with the FeatureBits information we
7041 // changed above.
7042 getTargetStreamer().updateABIInfo(*this);
7043
7044 // If printing assembly, use the recently updated abiflags information.
7045 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7046 // emitted at the end).
7047 getTargetStreamer().emitDirectiveModuleOddSPReg();
7048
Toma Tabacuc405c822015-01-23 10:40:19 +00007049 // If this is not the end of the statement, report an error.
7050 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7051 reportParseError("unexpected token, expected end of statement");
7052 return false;
7053 }
7054
7055 return false; // parseDirectiveModule has finished successfully.
7056 } else if (Option == "fp") {
7057 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007058 } else if (Option == "softfloat") {
7059 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7060
7061 // Synchronize the ABI Flags information with the FeatureBits information we
7062 // updated above.
7063 getTargetStreamer().updateABIInfo(*this);
7064
7065 // If printing assembly, use the recently updated ABI Flags information.
7066 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7067 // emitted later).
7068 getTargetStreamer().emitDirectiveModuleSoftFloat();
7069
7070 // If this is not the end of the statement, report an error.
7071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7072 reportParseError("unexpected token, expected end of statement");
7073 return false;
7074 }
7075
7076 return false; // parseDirectiveModule has finished successfully.
7077 } else if (Option == "hardfloat") {
7078 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7079
7080 // Synchronize the ABI Flags information with the FeatureBits information we
7081 // updated above.
7082 getTargetStreamer().updateABIInfo(*this);
7083
7084 // If printing assembly, use the recently updated ABI Flags information.
7085 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7086 // emitted later).
7087 getTargetStreamer().emitDirectiveModuleHardFloat();
7088
7089 // If this is not the end of the statement, report an error.
7090 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7091 reportParseError("unexpected token, expected end of statement");
7092 return false;
7093 }
7094
7095 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007096 } else {
7097 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7098 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007099}
7100
7101/// parseDirectiveModuleFP
7102/// ::= =32
7103/// ::= =xx
7104/// ::= =64
7105bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007106 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007107 MCAsmLexer &Lexer = getLexer();
7108
7109 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007110 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007111 return false;
7112 }
7113 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007114
Daniel Sanders7e527422014-07-10 13:38:23 +00007115 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007116 if (!parseFpABIValue(FpABI, ".module"))
7117 return false;
7118
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007119 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007120 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007121 return false;
7122 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007123
Toma Tabacua64e5402015-06-25 12:44:38 +00007124 // Synchronize the abiflags information with the FeatureBits information we
7125 // changed above.
7126 getTargetStreamer().updateABIInfo(*this);
7127
7128 // If printing assembly, use the recently updated abiflags information.
7129 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7130 // emitted at the end).
7131 getTargetStreamer().emitDirectiveModuleFP();
7132
Daniel Sanders7e527422014-07-10 13:38:23 +00007133 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007134 return false;
7135}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007136
Daniel Sanders7e527422014-07-10 13:38:23 +00007137bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007138 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007139 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007140 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007141 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007142
7143 if (Lexer.is(AsmToken::Identifier)) {
7144 StringRef Value = Parser.getTok().getString();
7145 Parser.Lex();
7146
7147 if (Value != "xx") {
7148 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7149 return false;
7150 }
7151
7152 if (!isABI_O32()) {
7153 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7154 return false;
7155 }
7156
Daniel Sanders7e527422014-07-10 13:38:23 +00007157 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007158 if (ModuleLevelOptions) {
7159 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7160 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7161 } else {
7162 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7163 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7164 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007165 return true;
7166 }
7167
7168 if (Lexer.is(AsmToken::Integer)) {
7169 unsigned Value = Parser.getTok().getIntVal();
7170 Parser.Lex();
7171
7172 if (Value != 32 && Value != 64) {
7173 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7174 return false;
7175 }
7176
7177 if (Value == 32) {
7178 if (!isABI_O32()) {
7179 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7180 return false;
7181 }
7182
Daniel Sanders7e527422014-07-10 13:38:23 +00007183 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007184 if (ModuleLevelOptions) {
7185 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7186 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7187 } else {
7188 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7189 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7190 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007191 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007192 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007193 if (ModuleLevelOptions) {
7194 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7195 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7196 } else {
7197 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7198 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7199 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007200 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007201
Daniel Sanders7e527422014-07-10 13:38:23 +00007202 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007203 }
7204
7205 return false;
7206}
7207
Jack Carter0b744b32012-10-04 02:29:46 +00007208bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007209 // This returns false if this function recognizes the directive
7210 // regardless of whether it is successfully handles or reports an
7211 // error. Otherwise it returns true to give the generic parser a
7212 // chance at recognizing it.
7213
Rafael Espindola961d4692014-11-11 05:18:41 +00007214 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007215 StringRef IDVal = DirectiveID.getString();
7216
Nirav Dave996fc132016-05-05 14:15:46 +00007217 if (IDVal == ".cpload") {
7218 parseDirectiveCpLoad(DirectiveID.getLoc());
7219 return false;
7220 }
7221 if (IDVal == ".cprestore") {
7222 parseDirectiveCpRestore(DirectiveID.getLoc());
7223 return false;
7224 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007225 if (IDVal == ".dword") {
7226 parseDataDirective(8, DirectiveID.getLoc());
7227 return false;
7228 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007229 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007230 StringRef SymbolName;
7231
7232 if (Parser.parseIdentifier(SymbolName)) {
7233 reportParseError("expected identifier after .ent");
7234 return false;
7235 }
7236
7237 // There's an undocumented extension that allows an integer to
7238 // follow the name of the procedure which AFAICS is ignored by GAS.
7239 // Example: .ent foo,2
7240 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7241 if (getLexer().isNot(AsmToken::Comma)) {
7242 // Even though we accept this undocumented extension for compatibility
7243 // reasons, the additional integer argument does not actually change
7244 // the behaviour of the '.ent' directive, so we would like to discourage
7245 // its use. We do this by not referring to the extended version in
7246 // error messages which are not directly related to its use.
7247 reportParseError("unexpected token, expected end of statement");
7248 return false;
7249 }
7250 Parser.Lex(); // Eat the comma.
7251 const MCExpr *DummyNumber;
7252 int64_t DummyNumberVal;
7253 // If the user was explicitly trying to use the extended version,
7254 // we still give helpful extension-related error messages.
7255 if (Parser.parseExpression(DummyNumber)) {
7256 reportParseError("expected number after comma");
7257 return false;
7258 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007259 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007260 reportParseError("expected an absolute expression after comma");
7261 return false;
7262 }
7263 }
7264
7265 // If this is not the end of the statement, report an error.
7266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7267 reportParseError("unexpected token, expected end of statement");
7268 return false;
7269 }
7270
Jim Grosbach6f482002015-05-18 18:43:14 +00007271 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007272
7273 getTargetStreamer().emitDirectiveEnt(*Sym);
7274 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007275 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007276 return false;
7277 }
7278
Jack Carter07c818d2013-01-25 01:31:34 +00007279 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007280 StringRef SymbolName;
7281
7282 if (Parser.parseIdentifier(SymbolName)) {
7283 reportParseError("expected identifier after .end");
7284 return false;
7285 }
7286
7287 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7288 reportParseError("unexpected token, expected end of statement");
7289 return false;
7290 }
7291
7292 if (CurrentFn == nullptr) {
7293 reportParseError(".end used without .ent");
7294 return false;
7295 }
7296
7297 if ((SymbolName != CurrentFn->getName())) {
7298 reportParseError(".end symbol does not match .ent symbol");
7299 return false;
7300 }
7301
7302 getTargetStreamer().emitDirectiveEnd(SymbolName);
7303 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007304 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007305 return false;
7306 }
7307
Jack Carter07c818d2013-01-25 01:31:34 +00007308 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007309 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7310 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007311 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007312 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7313 reportParseError("expected stack register");
7314 return false;
7315 }
7316
7317 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7318 if (!StackRegOpnd.isGPRAsmReg()) {
7319 reportParseError(StackRegOpnd.getStartLoc(),
7320 "expected general purpose register");
7321 return false;
7322 }
7323 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7324
7325 if (Parser.getTok().is(AsmToken::Comma))
7326 Parser.Lex();
7327 else {
7328 reportParseError("unexpected token, expected comma");
7329 return false;
7330 }
7331
7332 // Parse the frame size.
7333 const MCExpr *FrameSize;
7334 int64_t FrameSizeVal;
7335
7336 if (Parser.parseExpression(FrameSize)) {
7337 reportParseError("expected frame size value");
7338 return false;
7339 }
7340
Jim Grosbach13760bd2015-05-30 01:25:56 +00007341 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007342 reportParseError("frame size not an absolute expression");
7343 return false;
7344 }
7345
7346 if (Parser.getTok().is(AsmToken::Comma))
7347 Parser.Lex();
7348 else {
7349 reportParseError("unexpected token, expected comma");
7350 return false;
7351 }
7352
7353 // Parse the return register.
7354 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007355 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007356 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7357 reportParseError("expected return register");
7358 return false;
7359 }
7360
7361 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7362 if (!ReturnRegOpnd.isGPRAsmReg()) {
7363 reportParseError(ReturnRegOpnd.getStartLoc(),
7364 "expected general purpose register");
7365 return false;
7366 }
7367
7368 // If this is not the end of the statement, report an error.
7369 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7370 reportParseError("unexpected token, expected end of statement");
7371 return false;
7372 }
7373
7374 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7375 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007376 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007377 return false;
7378 }
7379
Jack Carter07c818d2013-01-25 01:31:34 +00007380 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007381 parseDirectiveSet();
7382 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007383 }
7384
Daniel Sandersd97a6342014-08-13 10:07:34 +00007385 if (IDVal == ".mask" || IDVal == ".fmask") {
7386 // .mask bitmask, frame_offset
7387 // bitmask: One bit for each register used.
7388 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7389 // first register is expected to be saved.
7390 // Examples:
7391 // .mask 0x80000000, -4
7392 // .fmask 0x80000000, -4
7393 //
Jack Carterbe332172012-09-07 00:48:02 +00007394
Daniel Sandersd97a6342014-08-13 10:07:34 +00007395 // Parse the bitmask
7396 const MCExpr *BitMask;
7397 int64_t BitMaskVal;
7398
7399 if (Parser.parseExpression(BitMask)) {
7400 reportParseError("expected bitmask value");
7401 return false;
7402 }
7403
Jim Grosbach13760bd2015-05-30 01:25:56 +00007404 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007405 reportParseError("bitmask not an absolute expression");
7406 return false;
7407 }
7408
7409 if (Parser.getTok().is(AsmToken::Comma))
7410 Parser.Lex();
7411 else {
7412 reportParseError("unexpected token, expected comma");
7413 return false;
7414 }
7415
7416 // Parse the frame_offset
7417 const MCExpr *FrameOffset;
7418 int64_t FrameOffsetVal;
7419
7420 if (Parser.parseExpression(FrameOffset)) {
7421 reportParseError("expected frame offset value");
7422 return false;
7423 }
7424
Jim Grosbach13760bd2015-05-30 01:25:56 +00007425 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007426 reportParseError("frame offset not an absolute expression");
7427 return false;
7428 }
7429
7430 // If this is not the end of the statement, report an error.
7431 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7432 reportParseError("unexpected token, expected end of statement");
7433 return false;
7434 }
7435
7436 if (IDVal == ".mask")
7437 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7438 else
7439 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007440 return false;
7441 }
7442
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007443 if (IDVal == ".nan")
7444 return parseDirectiveNaN();
7445
Jack Carter07c818d2013-01-25 01:31:34 +00007446 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007447 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007448 return false;
7449 }
7450
Rafael Espindolab59fb732014-03-28 18:50:26 +00007451 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007452 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007453 return false;
7454 }
7455
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007456 if (IDVal == ".dtprelword") {
7457 parseDirectiveDtpRelWord();
7458 return false;
7459 }
7460
7461 if (IDVal == ".dtpreldword") {
7462 parseDirectiveDtpRelDWord();
7463 return false;
7464 }
7465
7466 if (IDVal == ".tprelword") {
7467 parseDirectiveTpRelWord();
7468 return false;
7469 }
7470
7471 if (IDVal == ".tpreldword") {
7472 parseDirectiveTpRelDWord();
7473 return false;
7474 }
7475
Jack Carter07c818d2013-01-25 01:31:34 +00007476 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007477 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007478 return false;
7479 }
7480
Scott Egertond1aeb052016-02-15 16:11:51 +00007481 if (IDVal == ".hword") {
7482 parseDataDirective(2, DirectiveID.getLoc());
7483 return false;
7484 }
7485
Nirav Dave996fc132016-05-05 14:15:46 +00007486 if (IDVal == ".option") {
7487 parseDirectiveOption();
7488 return false;
7489 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007490
7491 if (IDVal == ".abicalls") {
7492 getTargetStreamer().emitDirectiveAbiCalls();
7493 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007494 Error(Parser.getTok().getLoc(),
7495 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007496 }
7497 return false;
7498 }
7499
Nirav Dave996fc132016-05-05 14:15:46 +00007500 if (IDVal == ".cpsetup") {
7501 parseDirectiveCPSetup();
7502 return false;
7503 }
7504 if (IDVal == ".cpreturn") {
7505 parseDirectiveCPReturn();
7506 return false;
7507 }
7508 if (IDVal == ".module") {
7509 parseDirectiveModule();
7510 return false;
7511 }
7512 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7513 parseInternalDirectiveReallowModule();
7514 return false;
7515 }
7516 if (IDVal == ".insn") {
7517 parseInsnDirective();
7518 return false;
7519 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007520 if (IDVal == ".rdata") {
7521 parseRSectionDirective(".rodata");
7522 return false;
7523 }
Nirav Dave996fc132016-05-05 14:15:46 +00007524 if (IDVal == ".sbss") {
7525 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7526 return false;
7527 }
7528 if (IDVal == ".sdata") {
7529 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7530 return false;
7531 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007532
Rafael Espindola870c4e92012-01-11 03:56:41 +00007533 return true;
7534}
7535
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007536bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7537 // If this is not the end of the statement, report an error.
7538 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7539 reportParseError("unexpected token, expected end of statement");
7540 return false;
7541 }
7542
7543 getTargetStreamer().reallowModuleDirective();
7544
7545 getParser().Lex(); // Eat EndOfStatement token.
7546 return false;
7547}
7548
Rafael Espindola870c4e92012-01-11 03:56:41 +00007549extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007550 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7551 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7552 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
7553 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00007554}
Jack Carterb4dbc172012-09-05 23:34:03 +00007555
7556#define GET_REGISTER_MATCHER
7557#define GET_MATCHER_IMPLEMENTATION
7558#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00007559
7560bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
7561 // Find the appropriate table for this asm variant.
7562 const MatchEntry *Start, *End;
7563 switch (VariantID) {
7564 default: llvm_unreachable("invalid variant!");
7565 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
7566 }
7567 // Search the table.
7568 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
7569 return MnemonicRange.first != MnemonicRange.second;
7570}