blob: 694c201cbe8dce54471f4b84cb0d34fc9f9080aa [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 Atanasyanbe186202016-02-11 06:45:54 +0000325 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000326
327 bool parseSetAtDirective();
328 bool parseSetNoAtDirective();
329 bool parseSetMacroDirective();
330 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000331 bool parseSetMsaDirective();
332 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000333 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000334 bool parseSetReorderDirective();
335 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000336 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000337 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000338 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000339 bool parseSetOddSPRegDirective();
340 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000341 bool parseSetPopDirective();
342 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000343 bool parseSetSoftFloatDirective();
344 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000345
Jack Carterd76b2372013-03-21 21:44:16 +0000346 bool parseSetAssignment();
347
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000348 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000349 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000350 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000351 bool parseDirectiveDtpRelWord();
352 bool parseDirectiveDtpRelDWord();
353 bool parseDirectiveTpRelWord();
354 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000355 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000356 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000357 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
358 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000359
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000360 bool parseInternalDirectiveReallowModule();
361
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000362 bool eatComma(StringRef ErrorStr);
363
Jack Carter1ac53222013-02-20 23:11:17 +0000364 int matchCPURegisterName(StringRef Symbol);
365
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000366 int matchHWRegsRegisterName(StringRef Symbol);
367
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000368 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000369
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000370 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000371
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000372 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000373
Jack Carter5dc8ac92013-09-25 23:50:44 +0000374 int matchMSA128RegisterName(StringRef Name);
375
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000376 int matchMSA128CtrlRegisterName(StringRef Name);
377
Jack Carterd0bd6422013-04-18 00:41:53 +0000378 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000379
Toma Tabacu89a712b2015-04-15 10:48:56 +0000380 /// Returns the internal register number for the current AT. Also checks if
381 /// the current AT is unavailable (set to $0) and gives an error if it is.
382 /// This should be used in pseudo-instruction expansions which need AT.
383 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000384
Simon Dardis3aa8a902017-02-06 12:43:46 +0000385 bool canUseATReg();
386
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000387 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
388 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000389
390 // Helper function that checks if the value of a vector index is within the
391 // boundaries of accepted values for each RegisterKind
392 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
393 bool validateMSAIndex(int Val, int RegKind);
394
Daniel Sandersf0df2212014-08-04 12:20:00 +0000395 // Selects a new architecture by updating the FeatureBits with the necessary
396 // info including implied dependencies.
397 // Internally, it clears all the feature bits related to *any* architecture
398 // and selects the new one using the ToggleFeature functionality of the
399 // MCSubtargetInfo object that handles implied dependencies. The reason we
400 // clear all the arch related bits manually is because ToggleFeature only
401 // clears the features that imply the feature being cleared and not the
402 // features implied by the feature being cleared. This is easier to see
403 // with an example:
404 // --------------------------------------------------
405 // | Feature | Implies |
406 // | -------------------------------------------------|
407 // | FeatureMips1 | None |
408 // | FeatureMips2 | FeatureMips1 |
409 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
410 // | FeatureMips4 | FeatureMips3 |
411 // | ... | |
412 // --------------------------------------------------
413 //
414 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
415 // FeatureMipsGP64 | FeatureMips1)
416 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
417 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000418 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000419 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000420 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
421 STI.setFeatureBits(FeatureBits);
422 setAvailableFeatures(
423 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000424 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000425 }
426
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000427 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000428 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000429 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000430 setAvailableFeatures(
431 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000432 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000433 }
434 }
435
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000436 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000437 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000438 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000439 setAvailableFeatures(
440 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000441 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000442 }
443 }
444
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000445 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
446 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000447 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000448 }
449
450 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
451 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000452 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000453 }
454
Rafael Espindola870c4e92012-01-11 03:56:41 +0000455public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000456 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000457 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000458 Match_RequiresDifferentOperands,
459 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000460 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000461 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000462 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000463#define GET_OPERAND_DIAGNOSTIC_TYPES
464#include "MipsGenAsmMatcher.inc"
465#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000466 };
467
Akira Hatanakab11ef082015-11-14 06:35:56 +0000468 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000470 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000471 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
472 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000473 MCAsmParserExtension::Initialize(parser);
474
Toma Tabacu11e14a92015-04-21 11:50:52 +0000475 parser.addAliasForDirective(".asciiz", ".asciz");
476
Jack Carterb4dbc172012-09-05 23:34:03 +0000477 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000478 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000479
Toma Tabacu9db22db2014-09-09 10:15:38 +0000480 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000481 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000482 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000483
Toma Tabacu9db22db2014-09-09 10:15:38 +0000484 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000485 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000486 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000487
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 getTargetStreamer().updateABIInfo(*this);
489
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000490 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000491 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000492
493 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000494
Rafael Espindola699281c2016-05-18 11:58:50 +0000495 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000496
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000497 IsCpRestoreSet = false;
498 CpRestoreOffset = -1;
499
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000500 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000501 if ((TheTriple.getArch() == Triple::mips) ||
502 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000503 IsLittleEndian = false;
504 else
505 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000506 }
507
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000508 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
509 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
510
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 bool isGP64bit() const {
512 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
513 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000514
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000515 bool isFP64bit() const {
516 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
517 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000518
Eric Christophera5762812015-01-26 17:33:46 +0000519 const MipsABIInfo &getABI() const { return ABI; }
520 bool isABI_N32() const { return ABI.IsN32(); }
521 bool isABI_N64() const { return ABI.IsN64(); }
522 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool isABI_FPXX() const {
524 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
525 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000526
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000527 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000528 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000529 }
530
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000531 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000533 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000534
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 bool hasMips1() const {
536 return getSTI().getFeatureBits()[Mips::FeatureMips1];
537 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000538
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000539 bool hasMips2() const {
540 return getSTI().getFeatureBits()[Mips::FeatureMips2];
541 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000542
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000543 bool hasMips3() const {
544 return getSTI().getFeatureBits()[Mips::FeatureMips3];
545 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000546
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000547 bool hasMips4() const {
548 return getSTI().getFeatureBits()[Mips::FeatureMips4];
549 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000550
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000551 bool hasMips5() const {
552 return getSTI().getFeatureBits()[Mips::FeatureMips5];
553 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000554
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000555 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000556 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000557 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000558
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000559 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000560 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000561 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000562
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000563 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000564 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000565 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000566
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000567 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000568 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000570
Daniel Sanders17793142015-02-18 16:24:50 +0000571 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000572 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000573 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000574
Daniel Sanders17793142015-02-18 16:24:50 +0000575 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000577 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000578
Daniel Sanders17793142015-02-18 16:24:50 +0000579 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000581 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000582
Daniel Sanders17793142015-02-18 16:24:50 +0000583 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000585 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000586
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000587 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000590
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000591 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000592 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000593 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000594
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000595 bool hasDSP() const {
596 return getSTI().getFeatureBits()[Mips::FeatureDSP];
597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000598
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000599 bool hasDSPR2() const {
600 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000602
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000603 bool hasDSPR3() const {
604 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
605 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000606
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000607 bool hasMSA() const {
608 return getSTI().getFeatureBits()[Mips::FeatureMSA];
609 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000610
Kai Nackee0245392015-01-27 19:11:28 +0000611 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000612 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000613 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000614
Daniel Sandersa6994442015-08-18 12:33:54 +0000615 bool inPicMode() {
616 return IsPicEnabled;
617 }
618
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000619 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000620 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000621 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000622
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000623 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000624 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000625 }
626
Eric Christophere8ae3e32015-05-07 23:10:21 +0000627 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000628 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000629 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000630
Toma Tabacud9d344b2015-04-27 14:05:04 +0000631 /// Warn if RegIndex is the same as the current AT.
632 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000633
634 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000635
636 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000637
638 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
639 AsmToken::TokenKind OperatorToken,
640 MCContext &Ctx) override {
641 switch(OperatorToken) {
642 default:
643 llvm_unreachable("Unknown token");
644 return nullptr;
645 case AsmToken::PercentCall16:
646 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
647 case AsmToken::PercentCall_Hi:
648 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
649 case AsmToken::PercentCall_Lo:
650 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
651 case AsmToken::PercentDtprel_Hi:
652 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
653 case AsmToken::PercentDtprel_Lo:
654 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
655 case AsmToken::PercentGot:
656 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
657 case AsmToken::PercentGot_Disp:
658 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
659 case AsmToken::PercentGot_Hi:
660 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
661 case AsmToken::PercentGot_Lo:
662 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
663 case AsmToken::PercentGot_Ofst:
664 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
665 case AsmToken::PercentGot_Page:
666 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
667 case AsmToken::PercentGottprel:
668 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
669 case AsmToken::PercentGp_Rel:
670 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
671 case AsmToken::PercentHi:
672 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
673 case AsmToken::PercentHigher:
674 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
675 case AsmToken::PercentHighest:
676 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
677 case AsmToken::PercentLo:
678 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
679 case AsmToken::PercentNeg:
680 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
681 case AsmToken::PercentPcrel_Hi:
682 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
683 case AsmToken::PercentPcrel_Lo:
684 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
685 case AsmToken::PercentTlsgd:
686 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
687 case AsmToken::PercentTlsldm:
688 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
689 case AsmToken::PercentTprel_Hi:
690 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
691 case AsmToken::PercentTprel_Lo:
692 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
693 }
694 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000695};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000696
697/// MipsOperand - Instances of this class represent a parsed Mips machine
698/// instruction.
699class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000700public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000701 /// Broad categories of register classes
702 /// The exact class is finalized by the render method.
703 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000704 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000705 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000706 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 RegKind_FCC = 4, /// FCC
708 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
709 RegKind_MSACtrl = 16, /// MSA control registers
710 RegKind_COP2 = 32, /// COP2
711 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
712 /// context).
713 RegKind_CCR = 128, /// CCR
714 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000715 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000716 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000717 /// Potentially any (e.g. $1)
718 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
719 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000720 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000721 };
722
723private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000724 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000725 k_Immediate, /// An immediate (possibly involving symbol references)
726 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000727 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000728 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000729 k_RegList, /// A physical register list
730 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000731 } Kind;
732
David Blaikie960ea3f2014-06-08 16:18:35 +0000733public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000734 MipsOperand(KindTy K, MipsAsmParser &Parser)
735 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
736
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000737 ~MipsOperand() override {
738 switch (Kind) {
739 case k_Immediate:
740 break;
741 case k_Memory:
742 delete Mem.Base;
743 break;
744 case k_RegList:
745 delete RegList.List;
746 case k_RegisterIndex:
747 case k_Token:
748 case k_RegPair:
749 break;
750 }
751 }
752
David Blaikie960ea3f2014-06-08 16:18:35 +0000753private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000754 /// For diagnostics, and checking the assembler temporary
755 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000756
Eric Christopher8996c5d2013-03-15 00:42:55 +0000757 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000758 const char *Data;
759 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000760 };
761
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000762 struct RegIdxOp {
763 unsigned Index; /// Index into the register class
764 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000765 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000767 };
768
769 struct ImmOp {
770 const MCExpr *Val;
771 };
772
773 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000775 const MCExpr *Off;
776 };
777
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000778 struct RegListOp {
779 SmallVector<unsigned, 10> *List;
780 };
781
Jack Carterb4dbc172012-09-05 23:34:03 +0000782 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000783 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000785 struct ImmOp Imm;
786 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000787 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000788 };
789
790 SMLoc StartLoc, EndLoc;
791
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000793 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
794 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000795 const MCRegisterInfo *RegInfo,
796 SMLoc S, SMLoc E,
797 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000798 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 Op->RegIdx.Index = Index;
800 Op->RegIdx.RegInfo = RegInfo;
801 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000802 Op->RegIdx.Tok.Data = Str.data();
803 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 Op->StartLoc = S;
805 Op->EndLoc = E;
806 return Op;
807 }
808
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000809public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 /// Coerce the register to GPR32 and return the real register for the current
811 /// target.
812 unsigned getGPR32Reg() const {
813 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000814 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 unsigned ClassID = Mips::GPR32RegClassID;
816 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000817 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000818
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000819 /// Coerce the register to GPR32 and return the real register for the current
820 /// target.
821 unsigned getGPRMM16Reg() const {
822 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
823 unsigned ClassID = Mips::GPR32RegClassID;
824 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
825 }
826
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 /// Coerce the register to GPR64 and return the real register for the current
828 /// target.
829 unsigned getGPR64Reg() const {
830 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
831 unsigned ClassID = Mips::GPR64RegClassID;
832 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000833 }
834
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835private:
836 /// Coerce the register to AFGR64 and return the real register for the current
837 /// target.
838 unsigned getAFGR64Reg() const {
839 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
840 if (RegIdx.Index % 2 != 0)
841 AsmParser.Warning(StartLoc, "Float register should be even.");
842 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
843 .getRegister(RegIdx.Index / 2);
844 }
845
846 /// Coerce the register to FGR64 and return the real register for the current
847 /// target.
848 unsigned getFGR64Reg() const {
849 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
850 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
851 .getRegister(RegIdx.Index);
852 }
853
854 /// Coerce the register to FGR32 and return the real register for the current
855 /// target.
856 unsigned getFGR32Reg() const {
857 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
858 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
859 .getRegister(RegIdx.Index);
860 }
861
862 /// Coerce the register to FGRH32 and return the real register for the current
863 /// target.
864 unsigned getFGRH32Reg() const {
865 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
866 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
867 .getRegister(RegIdx.Index);
868 }
869
870 /// Coerce the register to FCC and return the real register for the current
871 /// target.
872 unsigned getFCCReg() const {
873 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
874 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
875 .getRegister(RegIdx.Index);
876 }
877
878 /// Coerce the register to MSA128 and return the real register for the current
879 /// target.
880 unsigned getMSA128Reg() const {
881 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
882 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
883 // identical
884 unsigned ClassID = Mips::MSA128BRegClassID;
885 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
886 }
887
888 /// Coerce the register to MSACtrl and return the real register for the
889 /// current target.
890 unsigned getMSACtrlReg() const {
891 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
892 unsigned ClassID = Mips::MSACtrlRegClassID;
893 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
894 }
895
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000896 /// Coerce the register to COP0 and return the real register for the
897 /// current target.
898 unsigned getCOP0Reg() const {
899 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
900 unsigned ClassID = Mips::COP0RegClassID;
901 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
902 }
903
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000904 /// Coerce the register to COP2 and return the real register for the
905 /// current target.
906 unsigned getCOP2Reg() const {
907 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
908 unsigned ClassID = Mips::COP2RegClassID;
909 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
910 }
911
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000912 /// Coerce the register to COP3 and return the real register for the
913 /// current target.
914 unsigned getCOP3Reg() const {
915 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
916 unsigned ClassID = Mips::COP3RegClassID;
917 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
918 }
919
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000920 /// Coerce the register to ACC64DSP and return the real register for the
921 /// current target.
922 unsigned getACC64DSPReg() const {
923 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
924 unsigned ClassID = Mips::ACC64DSPRegClassID;
925 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
926 }
927
928 /// Coerce the register to HI32DSP and return the real register for the
929 /// current target.
930 unsigned getHI32DSPReg() const {
931 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
932 unsigned ClassID = Mips::HI32DSPRegClassID;
933 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
934 }
935
936 /// Coerce the register to LO32DSP and return the real register for the
937 /// current target.
938 unsigned getLO32DSPReg() const {
939 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
940 unsigned ClassID = Mips::LO32DSPRegClassID;
941 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
942 }
943
944 /// Coerce the register to CCR and return the real register for the
945 /// current target.
946 unsigned getCCRReg() const {
947 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
948 unsigned ClassID = Mips::CCRRegClassID;
949 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
950 }
951
952 /// Coerce the register to HWRegs and return the real register for the
953 /// current target.
954 unsigned getHWRegsReg() const {
955 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
956 unsigned ClassID = Mips::HWRegsRegClassID;
957 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
958 }
959
960public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000961 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000962 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000963 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000964 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000965 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000966 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000967 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000968 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000969 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000970
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000971 void addRegOperands(MCInst &Inst, unsigned N) const {
972 llvm_unreachable("Use a custom parser instead");
973 }
974
Daniel Sanders21bce302014-04-01 12:35:23 +0000975 /// Render the operand to an MCInst as a GPR32
976 /// Asserts if the wrong number of operands are requested, or the operand
977 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000978 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
979 assert(N == 1 && "Invalid number of operands!");
980 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
981 }
982
983 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
984 assert(N == 1 && "Invalid number of operands!");
985 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
986 }
987
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000988 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000990 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 }
992
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000993 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000996 }
997
Jozef Kolek1904fa22014-11-24 14:25:53 +0000998 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
999 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001000 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001001 }
1002
Zoran Jovanovic41688672015-02-10 16:36:20 +00001003 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1004 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001006 }
1007
Daniel Sanders21bce302014-04-01 12:35:23 +00001008 /// Render the operand to an MCInst as a GPR64
1009 /// Asserts if the wrong number of operands are requested, or the operand
1010 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1012 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001013 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001014 }
1015
1016 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1017 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001018 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001019 }
1020
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001021 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1022 assert(N == 1 && "Invalid number of operands!");
1023 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1024 }
1025
1026 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1027 assert(N == 1 && "Invalid number of operands!");
1028 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1029 }
1030
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1032 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001033 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 }
1035
1036 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1037 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001038 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001039 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001040 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001041 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001042 AsmParser.getParser().printError(
1043 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1044 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 }
1046
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001047 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
1049 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1050 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1051 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1052 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1053 "registers");
1054 }
1055
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1057 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001058 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001059 }
1060
1061 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001063 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001064 }
1065
1066 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1067 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001068 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001069 }
1070
1071 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1072 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001073 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 }
1075
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001076 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1077 assert(N == 1 && "Invalid number of operands!");
1078 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1079 }
1080
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001081 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1082 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001083 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001084 }
1085
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001086 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1087 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001088 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001089 }
1090
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001091 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1092 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001093 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001094 }
1095
1096 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1097 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001098 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001099 }
1100
1101 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1102 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001103 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001104 }
1105
1106 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1107 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001108 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001109 }
1110
1111 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001113 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001114 }
1115
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001116 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001117 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001119 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001120 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001121 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001122 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001123 Inst.addOperand(MCOperand::createImm(Imm));
1124 }
1125
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001126 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001127 void addSImmOperands(MCInst &Inst, unsigned N) const {
1128 if (isImm() && !isConstantImm()) {
1129 addExpr(Inst, getImm());
1130 return;
1131 }
1132 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1133 }
1134
1135 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001136 void addUImmOperands(MCInst &Inst, unsigned N) const {
1137 if (isImm() && !isConstantImm()) {
1138 addExpr(Inst, getImm());
1139 return;
1140 }
1141 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1142 }
1143
Daniel Sanders78e89022016-03-11 11:37:50 +00001144 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1145 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
1147 int64_t Imm = getConstantImm() - Offset;
1148 Imm = SignExtend64<Bits>(Imm);
1149 Imm += Offset;
1150 Imm += AdjustOffset;
1151 Inst.addOperand(MCOperand::createImm(Imm));
1152 }
1153
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001154 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001155 assert(N == 1 && "Invalid number of operands!");
1156 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001157 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001158 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001159
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001160 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001161 assert(N == 2 && "Invalid number of operands!");
1162
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001163 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1164 ? getMemBase()->getGPR64Reg()
1165 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001166
1167 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001168 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001169 }
1170
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001171 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1172 assert(N == 2 && "Invalid number of operands!");
1173
Jim Grosbache9119e42015-05-13 18:37:00 +00001174 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001175
1176 const MCExpr *Expr = getMemOff();
1177 addExpr(Inst, Expr);
1178 }
1179
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001180 void addRegListOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182
1183 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001184 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001185 }
1186
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001187 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1188 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001189 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001190 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001191 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1192 Inst.addOperand(MCOperand::createReg(
1193 RegIdx.RegInfo->getRegClass(
1194 AsmParser.getABI().AreGprs64bit()
1195 ? Mips::GPR64RegClassID
1196 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1197 Inst.addOperand(MCOperand::createReg(
1198 RegIdx.RegInfo->getRegClass(
1199 AsmParser.getABI().AreGprs64bit()
1200 ? Mips::GPR64RegClassID
1201 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001202 }
1203
Zoran Jovanovic41688672015-02-10 16:36:20 +00001204 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1205 assert(N == 2 && "Invalid number of operands!");
1206 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001207 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001208 }
1209
Craig Topper56c590a2014-04-29 07:58:02 +00001210 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001211 // As a special case until we sort out the definition of div/divu, accept
1212 // $0/$zero here so that MCK_ZERO works correctly.
1213 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001214 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001215
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001216 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001217 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001218
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001220 int64_t Res;
1221 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001222 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001223
Daniel Sanders52da7af2015-11-06 12:11:03 +00001224 bool isConstantImmz() const {
1225 return isConstantImm() && getConstantImm() == 0;
1226 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001227
Daniel Sandersea4f6532015-11-06 12:22:31 +00001228 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1229 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1230 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001231
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001232 template <unsigned Bits> bool isSImm() const {
1233 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1234 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001235
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001236 template <unsigned Bits> bool isUImm() const {
1237 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1238 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001239
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001240 template <unsigned Bits> bool isAnyImm() const {
1241 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1242 isUInt<Bits>(getConstantImm()))
1243 : isImm();
1244 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001245
Daniel Sanders78e89022016-03-11 11:37:50 +00001246 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1247 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001248 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001249
Hrvoje Varga46458d02016-02-25 12:53:29 +00001250 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1251 return isConstantImm() && getConstantImm() >= Bottom &&
1252 getConstantImm() <= Top;
1253 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001254
Craig Topper56c590a2014-04-29 07:58:02 +00001255 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001256 // Note: It's not possible to pretend that other operand kinds are tokens.
1257 // The matcher emitter checks tokens first.
1258 return Kind == k_Token;
1259 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001260
Craig Topper56c590a2014-04-29 07:58:02 +00001261 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001262
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001263 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001264 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001265 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Simon Dardis4ccda502016-05-27 13:56:36 +00001267 // Allow relocation operators.
1268 // FIXME: This predicate and others need to look through binary expressions
1269 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001270 template <unsigned Bits, unsigned ShiftAmount = 0>
1271 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001272 if (!isMem())
1273 return false;
1274 if (!getMemBase()->isGPRAsmReg())
1275 return false;
1276 if (isa<MCTargetExpr>(getMemOff()) ||
1277 (isConstantMemOff() &&
1278 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1279 return true;
1280 MCValue Res;
1281 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1282 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001283 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001284
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001285 bool isMemWithGRPMM16Base() const {
1286 return isMem() && getMemBase()->isMM16AsmReg();
1287 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001288
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001289 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1290 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1291 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1292 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001293
Jozef Kolek12c69822014-12-23 16:16:33 +00001294 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1295 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1296 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1297 && (getMemBase()->getGPR32Reg() == Mips::SP);
1298 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001299
Daniel Sanderse473dc92016-05-09 13:38:25 +00001300 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1301 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1302 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1303 && (getMemBase()->getGPR32Reg() == Mips::GP);
1304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001306 template <unsigned Bits, unsigned ShiftLeftAmount>
1307 bool isScaledUImm() const {
1308 return isConstantImm() &&
1309 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001310 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001311
Daniel Sanders97297772016-03-22 14:40:00 +00001312 template <unsigned Bits, unsigned ShiftLeftAmount>
1313 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001314 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1315 return true;
1316 // Operand can also be a symbol or symbol plus offset in case of relocations.
1317 if (Kind != k_Immediate)
1318 return false;
1319 MCValue Res;
1320 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1321 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001322 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001323
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001324 bool isRegList16() const {
1325 if (!isRegList())
1326 return false;
1327
1328 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001329 if (Size < 2 || Size > 5)
1330 return false;
1331
1332 unsigned R0 = RegList.List->front();
1333 unsigned R1 = RegList.List->back();
1334 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1335 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001336 return false;
1337
1338 int PrevReg = *RegList.List->begin();
1339 for (int i = 1; i < Size - 1; i++) {
1340 int Reg = (*(RegList.List))[i];
1341 if ( Reg != PrevReg + 1)
1342 return false;
1343 PrevReg = Reg;
1344 }
1345
1346 return true;
1347 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001348
Vladimir Medic2b953d02013-10-01 09:48:56 +00001349 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001350
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001351 bool isLSAImm() const {
1352 if (!isConstantImm())
1353 return false;
1354 int64_t Val = getConstantImm();
1355 return 1 <= Val && Val <= 4;
1356 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001357
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001358 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001359
Zoran Jovanovic41688672015-02-10 16:36:20 +00001360 bool isMovePRegPair() const {
1361 if (Kind != k_RegList || RegList.List->size() != 2)
1362 return false;
1363
1364 unsigned R0 = RegList.List->front();
1365 unsigned R1 = RegList.List->back();
1366
1367 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1368 (R0 == Mips::A1 && R1 == Mips::A3) ||
1369 (R0 == Mips::A2 && R1 == Mips::A3) ||
1370 (R0 == Mips::A0 && R1 == Mips::S5) ||
1371 (R0 == Mips::A0 && R1 == Mips::S6) ||
1372 (R0 == Mips::A0 && R1 == Mips::A1) ||
1373 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001374 (R0 == Mips::A0 && R1 == Mips::A3) ||
1375 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1376 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1377 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1378 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1379 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1380 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1381 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1382 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001383 return true;
1384
1385 return false;
1386 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001387
1388 StringRef getToken() const {
1389 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001390 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001391 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001392
Zlatko Buljanba553a62016-05-09 08:07:28 +00001393 bool isRegPair() const {
1394 return Kind == k_RegPair && RegIdx.Index <= 30;
1395 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001396
Craig Topper56c590a2014-04-29 07:58:02 +00001397 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001398 // As a special case until we sort out the definition of div/divu, accept
1399 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001400 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1401 RegIdx.Kind & RegKind_GPR)
1402 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001403
Daniel Sanders976d9382016-07-05 13:38:40 +00001404 llvm_unreachable("Invalid access!");
1405 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001406 }
1407
Jack Carterb4dbc172012-09-05 23:34:03 +00001408 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001409 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001410 return Imm.Val;
1411 }
1412
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001413 int64_t getConstantImm() const {
1414 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001415 int64_t Value = 0;
1416 (void)Val->evaluateAsAbsolute(Value);
1417 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001418 }
1419
1420 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001421 assert((Kind == k_Memory) && "Invalid access!");
1422 return Mem.Base;
1423 }
1424
1425 const MCExpr *getMemOff() const {
1426 assert((Kind == k_Memory) && "Invalid access!");
1427 return Mem.Off;
1428 }
1429
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001430 int64_t getConstantMemOff() const {
1431 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1432 }
1433
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001434 const SmallVectorImpl<unsigned> &getRegList() const {
1435 assert((Kind == k_RegList) && "Invalid access!");
1436 return *(RegList.List);
1437 }
1438
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001439 unsigned getRegPair() const {
1440 assert((Kind == k_RegPair) && "Invalid access!");
1441 return RegIdx.Index;
1442 }
1443
David Blaikie960ea3f2014-06-08 16:18:35 +00001444 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1445 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001446 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001447 Op->Tok.Data = Str.data();
1448 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001449 Op->StartLoc = S;
1450 Op->EndLoc = S;
1451 return Op;
1452 }
1453
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001454 /// Create a numeric register (e.g. $1). The exact register remains
1455 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001456 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001457 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1458 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001459 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001460 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001461 }
1462
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001463 /// Create a register that is definitely a GPR.
1464 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001465 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001466 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1467 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1468 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001469 }
1470
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001471 /// Create a register that is definitely a FGR.
1472 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001473 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001474 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1475 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1476 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001477 }
1478
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001479 /// Create a register that is definitely a HWReg.
1480 /// This is typically only used for named registers such as $hwr_cpunum.
1481 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001482 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001483 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001484 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001485 }
1486
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001487 /// Create a register that is definitely an FCC.
1488 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001489 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001490 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1491 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1492 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001493 }
1494
1495 /// Create a register that is definitely an ACC.
1496 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001497 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001498 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1499 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1500 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001501 }
1502
1503 /// Create a register that is definitely an MSA128.
1504 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001505 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001506 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1507 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1508 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001509 }
1510
1511 /// Create a register that is definitely an MSACtrl.
1512 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001513 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001514 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1515 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1516 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001517 }
1518
David Blaikie960ea3f2014-06-08 16:18:35 +00001519 static std::unique_ptr<MipsOperand>
1520 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001521 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001522 Op->Imm.Val = Val;
1523 Op->StartLoc = S;
1524 Op->EndLoc = E;
1525 return Op;
1526 }
1527
David Blaikie960ea3f2014-06-08 16:18:35 +00001528 static std::unique_ptr<MipsOperand>
1529 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1530 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001531 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001532 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001533 Op->Mem.Off = Off;
1534 Op->StartLoc = S;
1535 Op->EndLoc = E;
1536 return Op;
1537 }
1538
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001539 static std::unique_ptr<MipsOperand>
1540 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1541 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001542 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001543
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001544 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001545 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001546 Op->StartLoc = StartLoc;
1547 Op->EndLoc = EndLoc;
1548 return Op;
1549 }
1550
Daniel Sandersd044e492016-05-09 13:10:57 +00001551 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1552 SMLoc S, SMLoc E,
1553 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001554 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001555 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001556 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1557 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001558 Op->StartLoc = S;
1559 Op->EndLoc = E;
1560 return Op;
1561 }
1562
Simon Dardis509da1a2017-02-13 16:06:48 +00001563 bool isGPRZeroAsmReg() const {
1564 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1565 }
1566
1567 bool isGPRNonZeroAsmReg() const {
1568 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1569 RegIdx.Index <= 31;
1570 }
1571
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001572 bool isGPRAsmReg() const {
1573 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001575
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001576 bool isMM16AsmReg() const {
1577 if (!(isRegIdx() && RegIdx.Kind))
1578 return false;
1579 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1580 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001581
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001582 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001583 bool isMM16AsmRegZero() const {
1584 if (!(isRegIdx() && RegIdx.Kind))
1585 return false;
1586 return (RegIdx.Index == 0 ||
1587 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1588 RegIdx.Index == 17);
1589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001590
Zoran Jovanovic41688672015-02-10 16:36:20 +00001591 bool isMM16AsmRegMoveP() const {
1592 if (!(isRegIdx() && RegIdx.Kind))
1593 return false;
1594 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1595 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1596 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001597
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001598 bool isFGRAsmReg() const {
1599 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1600 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001602
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001603 bool isStrictlyFGRAsmReg() const {
1604 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1605 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1606 }
1607
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001608 bool isHWRegsAsmReg() const {
1609 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001610 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001611
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001612 bool isCCRAsmReg() const {
1613 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001614 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001615
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001616 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001617 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1618 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001619 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001620 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001621
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001622 bool isACCAsmReg() const {
1623 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001624 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001625
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001626 bool isCOP0AsmReg() const {
1627 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1628 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001629
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001630 bool isCOP2AsmReg() const {
1631 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001632 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001633
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001634 bool isCOP3AsmReg() const {
1635 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1636 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001637
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001638 bool isMSA128AsmReg() const {
1639 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001640 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001641
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001642 bool isMSACtrlAsmReg() const {
1643 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001644 }
1645
Jack Carterb4dbc172012-09-05 23:34:03 +00001646 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001647 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001648 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001649 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001650
Craig Topper56c590a2014-04-29 07:58:02 +00001651 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001652 switch (Kind) {
1653 case k_Immediate:
1654 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001655 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001656 OS << ">";
1657 break;
1658 case k_Memory:
1659 OS << "Mem<";
1660 Mem.Base->print(OS);
1661 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001662 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001663 OS << ">";
1664 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001665 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001666 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1667 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001668 break;
1669 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001670 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001671 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001672 case k_RegList:
1673 OS << "RegList< ";
1674 for (auto Reg : (*RegList.List))
1675 OS << Reg << " ";
1676 OS << ">";
1677 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001678 case k_RegPair:
1679 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1680 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001681 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001682 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001683
1684 bool isValidForTie(const MipsOperand &Other) const {
1685 if (Kind != Other.Kind)
1686 return false;
1687
1688 switch (Kind) {
1689 default:
1690 llvm_unreachable("Unexpected kind");
1691 return false;
1692 case k_RegisterIndex: {
1693 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1694 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1695 return Token == OtherToken;
1696 }
1697 }
1698 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001699}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001700
1701} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001702
Jack Carter9e65aa32013-03-22 00:05:30 +00001703namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001704
Jack Carter9e65aa32013-03-22 00:05:30 +00001705extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001706
1707} // end namespace llvm
1708
Jack Carter9e65aa32013-03-22 00:05:30 +00001709static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1710 return MipsInsts[Opcode];
1711}
1712
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001713static bool hasShortDelaySlot(unsigned Opcode) {
1714 switch (Opcode) {
1715 case Mips::JALS_MM:
1716 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001717 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001718 case Mips::BGEZALS_MM:
1719 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001720 return true;
1721 default:
1722 return false;
1723 }
1724}
1725
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001726static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1727 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1728 return &SRExpr->getSymbol();
1729 }
1730
1731 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1732 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1733 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1734
1735 if (LHSSym)
1736 return LHSSym;
1737
1738 if (RHSSym)
1739 return RHSSym;
1740
1741 return nullptr;
1742 }
1743
1744 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1745 return getSingleMCSymbol(UExpr->getSubExpr());
1746
1747 return nullptr;
1748}
1749
1750static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1751 if (isa<MCSymbolRefExpr>(Expr))
1752 return 1;
1753
1754 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1755 return countMCSymbolRefExpr(BExpr->getLHS()) +
1756 countMCSymbolRefExpr(BExpr->getRHS());
1757
1758 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1759 return countMCSymbolRefExpr(UExpr->getSubExpr());
1760
1761 return 0;
1762}
1763
Jack Carter9e65aa32013-03-22 00:05:30 +00001764bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001765 MCStreamer &Out,
1766 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001767 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001768 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001769 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001770
Jack Carter9e65aa32013-03-22 00:05:30 +00001771 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001772
1773 if (MCID.isBranch() || MCID.isCall()) {
1774 const unsigned Opcode = Inst.getOpcode();
1775 MCOperand Offset;
1776
1777 switch (Opcode) {
1778 default:
1779 break;
Kai Nackee0245392015-01-27 19:11:28 +00001780 case Mips::BBIT0:
1781 case Mips::BBIT032:
1782 case Mips::BBIT1:
1783 case Mips::BBIT132:
1784 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001785 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001786
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001787 case Mips::BEQ:
1788 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001789 case Mips::BEQ_MM:
1790 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001791 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001792 Offset = Inst.getOperand(2);
1793 if (!Offset.isImm())
1794 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001795 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001796 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001797 if (OffsetToAlignment(Offset.getImm(),
1798 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001799 return Error(IDLoc, "branch to misaligned address");
1800 break;
1801 case Mips::BGEZ:
1802 case Mips::BGTZ:
1803 case Mips::BLEZ:
1804 case Mips::BLTZ:
1805 case Mips::BGEZAL:
1806 case Mips::BLTZAL:
1807 case Mips::BC1F:
1808 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001809 case Mips::BGEZ_MM:
1810 case Mips::BGTZ_MM:
1811 case Mips::BLEZ_MM:
1812 case Mips::BLTZ_MM:
1813 case Mips::BGEZAL_MM:
1814 case Mips::BLTZAL_MM:
1815 case Mips::BC1F_MM:
1816 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001817 case Mips::BC1EQZC_MMR6:
1818 case Mips::BC1NEZC_MMR6:
1819 case Mips::BC2EQZC_MMR6:
1820 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001821 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001822 Offset = Inst.getOperand(1);
1823 if (!Offset.isImm())
1824 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001825 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001826 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001827 if (OffsetToAlignment(Offset.getImm(),
1828 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001829 return Error(IDLoc, "branch to misaligned address");
1830 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001831 case Mips::BGEC: case Mips::BGEC_MMR6:
1832 case Mips::BLTC: case Mips::BLTC_MMR6:
1833 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1834 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1835 case Mips::BEQC: case Mips::BEQC_MMR6:
1836 case Mips::BNEC: case Mips::BNEC_MMR6:
1837 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1838 Offset = Inst.getOperand(2);
1839 if (!Offset.isImm())
1840 break; // We'll deal with this situation later on when applying fixups.
1841 if (!isIntN(18, Offset.getImm()))
1842 return Error(IDLoc, "branch target out of range");
1843 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1844 return Error(IDLoc, "branch to misaligned address");
1845 break;
1846 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1847 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1848 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1849 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1850 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1851 Offset = Inst.getOperand(1);
1852 if (!Offset.isImm())
1853 break; // We'll deal with this situation later on when applying fixups.
1854 if (!isIntN(18, Offset.getImm()))
1855 return Error(IDLoc, "branch target out of range");
1856 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1857 return Error(IDLoc, "branch to misaligned address");
1858 break;
1859 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1860 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1861 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1862 Offset = Inst.getOperand(1);
1863 if (!Offset.isImm())
1864 break; // We'll deal with this situation later on when applying fixups.
1865 if (!isIntN(23, Offset.getImm()))
1866 return Error(IDLoc, "branch target out of range");
1867 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1868 return Error(IDLoc, "branch to misaligned address");
1869 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001870 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001871 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001872 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001873 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001874 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1875 Offset = Inst.getOperand(1);
1876 if (!Offset.isImm())
1877 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001878 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001879 return Error(IDLoc, "branch target out of range");
1880 if (OffsetToAlignment(Offset.getImm(), 2LL))
1881 return Error(IDLoc, "branch to misaligned address");
1882 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001883 }
1884 }
1885
Daniel Sandersa84989a2014-06-16 13:25:35 +00001886 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1887 // We still accept it but it is a normal nop.
1888 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1889 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1890 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1891 "nop instruction");
1892 }
1893
Kai Nackee0245392015-01-27 19:11:28 +00001894 if (hasCnMips()) {
1895 const unsigned Opcode = Inst.getOpcode();
1896 MCOperand Opnd;
1897 int Imm;
1898
1899 switch (Opcode) {
1900 default:
1901 break;
1902
1903 case Mips::BBIT0:
1904 case Mips::BBIT032:
1905 case Mips::BBIT1:
1906 case Mips::BBIT132:
1907 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1908 // The offset is handled above
1909 Opnd = Inst.getOperand(1);
1910 if (!Opnd.isImm())
1911 return Error(IDLoc, "expected immediate operand kind");
1912 Imm = Opnd.getImm();
1913 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1914 Opcode == Mips::BBIT1 ? 63 : 31))
1915 return Error(IDLoc, "immediate operand value out of range");
1916 if (Imm > 31) {
1917 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1918 : Mips::BBIT132);
1919 Inst.getOperand(1).setImm(Imm - 32);
1920 }
1921 break;
1922
Kai Nackee0245392015-01-27 19:11:28 +00001923 case Mips::SEQi:
1924 case Mips::SNEi:
1925 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1926 Opnd = Inst.getOperand(2);
1927 if (!Opnd.isImm())
1928 return Error(IDLoc, "expected immediate operand kind");
1929 Imm = Opnd.getImm();
1930 if (!isInt<10>(Imm))
1931 return Error(IDLoc, "immediate operand value out of range");
1932 break;
1933 }
1934 }
1935
Simon Dardis509da1a2017-02-13 16:06:48 +00001936 // Warn on division by zero. We're checking here as all instructions get
1937 // processed here, not just the macros that need expansion.
1938 //
1939 // The MIPS backend models most of the divison instructions and macros as
1940 // three operand instructions. The pre-R6 divide instructions however have
1941 // two operands and explicitly define HI/LO as part of the instruction,
1942 // not in the operands.
1943 unsigned FirstOp = 1;
1944 unsigned SecondOp = 2;
1945 switch (Inst.getOpcode()) {
1946 default:
1947 break;
1948 case Mips::SDivIMacro:
1949 case Mips::UDivIMacro:
1950 case Mips::DSDivIMacro:
1951 case Mips::DUDivIMacro:
1952 if (Inst.getOperand(2).getImm() == 0) {
1953 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1954 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1955 Warning(IDLoc, "dividing zero by zero");
1956 else
1957 Warning(IDLoc, "division by zero");
1958 }
1959 break;
1960 case Mips::DSDIV:
1961 case Mips::SDIV:
1962 case Mips::UDIV:
1963 case Mips::DUDIV:
1964 case Mips::UDIV_MM:
1965 case Mips::SDIV_MM:
1966 FirstOp = 0;
1967 SecondOp = 1;
1968 case Mips::SDivMacro:
1969 case Mips::DSDivMacro:
1970 case Mips::UDivMacro:
1971 case Mips::DUDivMacro:
1972 case Mips::DIV:
1973 case Mips::DIVU:
1974 case Mips::DDIV:
1975 case Mips::DDIVU:
1976 case Mips::DIVU_MMR6:
1977 case Mips::DDIVU_MM64R6:
1978 case Mips::DIV_MMR6:
1979 case Mips::DDIV_MM64R6:
1980 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1981 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1982 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1983 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1984 Warning(IDLoc, "dividing zero by zero");
1985 else
1986 Warning(IDLoc, "division by zero");
1987 }
1988 break;
1989 }
1990
Simon Atanasyan50485142016-12-12 17:40:26 +00001991 // For PIC code convert unconditional jump to unconditional branch.
1992 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1993 inPicMode()) {
1994 MCInst BInst;
1995 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1996 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1997 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1998 BInst.addOperand(Inst.getOperand(0));
1999 Inst = BInst;
2000 }
2001
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002002 // This expansion is not in a function called by tryExpandInstruction()
2003 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002004 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2005 inPicMode()) {
2006 warnIfNoMacro(IDLoc);
2007
2008 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2009
2010 // We can do this expansion if there's only 1 symbol in the argument
2011 // expression.
2012 if (countMCSymbolRefExpr(JalExpr) > 1)
2013 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2014
2015 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002016 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002017 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2018
2019 // FIXME: Add support for label+offset operands (currently causes an error).
2020 // FIXME: Add support for forward-declared local symbols.
2021 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002022 if (JalSym->isInSection() || JalSym->isTemporary() ||
2023 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002024 if (isABI_O32()) {
2025 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002026 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002027 // R_(MICRO)MIPS_GOT16 label
2028 // addiu $25, $25, 0
2029 // R_(MICRO)MIPS_LO16 label
2030 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002031 const MCExpr *Got16RelocExpr =
2032 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2033 const MCExpr *Lo16RelocExpr =
2034 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002035
Daniel Sandersa736b372016-04-29 13:33:12 +00002036 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2037 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2038 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2039 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002040 } else if (isABI_N32() || isABI_N64()) {
2041 // If it's a local symbol and the N32/N64 ABIs are being used,
2042 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002043 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002044 // R_(MICRO)MIPS_GOT_DISP label
2045 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002046 const MCExpr *GotDispRelocExpr =
2047 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002048
Daniel Sandersa736b372016-04-29 13:33:12 +00002049 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2050 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2051 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002052 }
2053 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002054 // If it's an external/weak symbol, we expand to:
2055 // lw/ld $25, 0($gp)
2056 // R_(MICRO)MIPS_CALL16 label
2057 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002058 const MCExpr *Call16RelocExpr =
2059 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002060
Daniel Sandersa736b372016-04-29 13:33:12 +00002061 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2062 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002063 }
2064
2065 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002066 if (IsCpRestoreSet && inMicroMipsMode())
2067 JalrInst.setOpcode(Mips::JALRS_MM);
2068 else
2069 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002070 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2071 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2072
2073 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2074 // This relocation is supposed to be an optimization hint for the linker
2075 // and is not necessary for correctness.
2076
2077 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002078 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002079 }
2080
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002081 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2082 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002083 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002084 // reference or immediate we may have to expand instructions.
2085 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002086 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002087 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2088 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002089 MCOperand &Op = Inst.getOperand(i);
2090 if (Op.isImm()) {
2091 int MemOffset = Op.getImm();
2092 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002094 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002095 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002096 }
2097 } else if (Op.isExpr()) {
2098 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002100 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002101 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002103 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002104 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002105 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002108 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002109 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002110 }
2111 }
2112 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002114 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002115
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002116 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002117 if (MCID.mayLoad()) {
2118 // Try to create 16-bit GP relative load instruction.
2119 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2120 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2121 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2122 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2123 MCOperand &Op = Inst.getOperand(i);
2124 if (Op.isImm()) {
2125 int MemOffset = Op.getImm();
2126 MCOperand &DstReg = Inst.getOperand(0);
2127 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002128 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002129 getContext().getRegisterInfo()->getRegClass(
2130 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002131 (BaseReg.getReg() == Mips::GP ||
2132 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002133
Daniel Sandersa736b372016-04-29 13:33:12 +00002134 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2135 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002136 return false;
2137 }
2138 }
2139 }
2140 } // for
2141 } // if load
2142
2143 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2144
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002145 MCOperand Opnd;
2146 int Imm;
2147
2148 switch (Inst.getOpcode()) {
2149 default:
2150 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002151 case Mips::ADDIUSP_MM:
2152 Opnd = Inst.getOperand(0);
2153 if (!Opnd.isImm())
2154 return Error(IDLoc, "expected immediate operand kind");
2155 Imm = Opnd.getImm();
2156 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2157 Imm % 4 != 0)
2158 return Error(IDLoc, "immediate operand value out of range");
2159 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002160 case Mips::SLL16_MM:
2161 case Mips::SRL16_MM:
2162 Opnd = Inst.getOperand(2);
2163 if (!Opnd.isImm())
2164 return Error(IDLoc, "expected immediate operand kind");
2165 Imm = Opnd.getImm();
2166 if (Imm < 1 || Imm > 8)
2167 return Error(IDLoc, "immediate operand value out of range");
2168 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002169 case Mips::LI16_MM:
2170 Opnd = Inst.getOperand(1);
2171 if (!Opnd.isImm())
2172 return Error(IDLoc, "expected immediate operand kind");
2173 Imm = Opnd.getImm();
2174 if (Imm < -1 || Imm > 126)
2175 return Error(IDLoc, "immediate operand value out of range");
2176 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002177 case Mips::ADDIUR2_MM:
2178 Opnd = Inst.getOperand(2);
2179 if (!Opnd.isImm())
2180 return Error(IDLoc, "expected immediate operand kind");
2181 Imm = Opnd.getImm();
2182 if (!(Imm == 1 || Imm == -1 ||
2183 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2184 return Error(IDLoc, "immediate operand value out of range");
2185 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002186 case Mips::ANDI16_MM:
2187 Opnd = Inst.getOperand(2);
2188 if (!Opnd.isImm())
2189 return Error(IDLoc, "expected immediate operand kind");
2190 Imm = Opnd.getImm();
2191 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2192 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2193 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2194 return Error(IDLoc, "immediate operand value out of range");
2195 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002196 case Mips::LBU16_MM:
2197 Opnd = Inst.getOperand(2);
2198 if (!Opnd.isImm())
2199 return Error(IDLoc, "expected immediate operand kind");
2200 Imm = Opnd.getImm();
2201 if (Imm < -1 || Imm > 14)
2202 return Error(IDLoc, "immediate operand value out of range");
2203 break;
2204 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002205 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002206 Opnd = Inst.getOperand(2);
2207 if (!Opnd.isImm())
2208 return Error(IDLoc, "expected immediate operand kind");
2209 Imm = Opnd.getImm();
2210 if (Imm < 0 || Imm > 15)
2211 return Error(IDLoc, "immediate operand value out of range");
2212 break;
2213 case Mips::LHU16_MM:
2214 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002215 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002216 Opnd = Inst.getOperand(2);
2217 if (!Opnd.isImm())
2218 return Error(IDLoc, "expected immediate operand kind");
2219 Imm = Opnd.getImm();
2220 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2221 return Error(IDLoc, "immediate operand value out of range");
2222 break;
2223 case Mips::LW16_MM:
2224 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002225 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002226 Opnd = Inst.getOperand(2);
2227 if (!Opnd.isImm())
2228 return Error(IDLoc, "expected immediate operand kind");
2229 Imm = Opnd.getImm();
2230 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2231 return Error(IDLoc, "immediate operand value out of range");
2232 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002233 case Mips::ADDIUPC_MM:
2234 MCOperand Opnd = Inst.getOperand(1);
2235 if (!Opnd.isImm())
2236 return Error(IDLoc, "expected immediate operand kind");
2237 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002238 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002239 return Error(IDLoc, "immediate operand value out of range");
2240 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002241 }
2242 }
2243
Daniel Sandersd8c07762016-04-18 12:35:36 +00002244 bool FillDelaySlot =
2245 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2246 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002247 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002248
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002249 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002250 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002251 switch (ExpandResult) {
2252 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002253 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002254 break;
2255 case MER_Success:
2256 break;
2257 case MER_Fail:
2258 return true;
2259 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002260
Daniel Sanderscda908a2016-05-16 09:10:13 +00002261 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2262 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2263 if (inMicroMipsMode())
2264 TOut.setUsesMicroMips();
2265
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002266 // If this instruction has a delay slot and .set reorder is active,
2267 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002268 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002269 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2270 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002271 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002272
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002273 if ((Inst.getOpcode() == Mips::JalOneReg ||
2274 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2275 isPicAndNotNxxAbi()) {
2276 if (IsCpRestoreSet) {
2277 // We need a NOP between the JALR and the LW:
2278 // If .set reorder has been used, we've already emitted a NOP.
2279 // If .set noreorder has been used, we need to emit a NOP at this point.
2280 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002281 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2282 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002283
2284 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002285 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002286 } else
2287 Warning(IDLoc, "no .cprestore used in PIC mode");
2288 }
2289
Jack Carter9e65aa32013-03-22 00:05:30 +00002290 return false;
2291}
2292
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002293MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002294MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2295 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002296 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002297 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002298 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002299 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002300 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002301 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002302 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002303 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002304 case Mips::LoadAddrImm64:
2305 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2306 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2307 "expected immediate operand kind");
2308
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002309 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2310 Inst.getOperand(1),
2311 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002312 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002313 ? MER_Fail
2314 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002315 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002316 case Mips::LoadAddrReg64:
2317 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2318 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2319 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2320 "expected immediate operand kind");
2321
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002322 return expandLoadAddress(Inst.getOperand(0).getReg(),
2323 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2324 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002325 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002326 ? MER_Fail
2327 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002328 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002329 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002330 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2331 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002332 case Mips::SWM_MM:
2333 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002334 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2335 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002336 case Mips::JalOneReg:
2337 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002338 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002339 case Mips::BneImm:
2340 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002341 case Mips::BEQLImmMacro:
2342 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002343 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002344 case Mips::BLT:
2345 case Mips::BLE:
2346 case Mips::BGE:
2347 case Mips::BGT:
2348 case Mips::BLTU:
2349 case Mips::BLEU:
2350 case Mips::BGEU:
2351 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002352 case Mips::BLTL:
2353 case Mips::BLEL:
2354 case Mips::BGEL:
2355 case Mips::BGTL:
2356 case Mips::BLTUL:
2357 case Mips::BLEUL:
2358 case Mips::BGEUL:
2359 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002360 case Mips::BLTImmMacro:
2361 case Mips::BLEImmMacro:
2362 case Mips::BGEImmMacro:
2363 case Mips::BGTImmMacro:
2364 case Mips::BLTUImmMacro:
2365 case Mips::BLEUImmMacro:
2366 case Mips::BGEUImmMacro:
2367 case Mips::BGTUImmMacro:
2368 case Mips::BLTLImmMacro:
2369 case Mips::BLELImmMacro:
2370 case Mips::BGELImmMacro:
2371 case Mips::BGTLImmMacro:
2372 case Mips::BLTULImmMacro:
2373 case Mips::BLEULImmMacro:
2374 case Mips::BGEULImmMacro:
2375 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002376 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002377 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002378 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002379 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2380 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002381 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002382 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002383 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2384 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002385 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002386 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002387 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2388 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002389 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002390 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002391 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2392 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002393 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002394 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2395 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002396 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002397 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002398 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002399 case Mips::PseudoTRUNC_W_D:
2400 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2401 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002402
2403 case Mips::LoadImmSingleGPR:
2404 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2405 ? MER_Fail
2406 : MER_Success;
2407 case Mips::LoadImmSingleFGR:
2408 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2409 ? MER_Fail
2410 : MER_Success;
2411 case Mips::LoadImmDoubleGPR:
2412 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2413 ? MER_Fail
2414 : MER_Success;
2415 case Mips::LoadImmDoubleFGR:
2416 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2417 ? MER_Fail
2418 : MER_Success;
2419 case Mips::LoadImmDoubleFGR_32:
2420 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2421 ? MER_Fail
2422 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002423 case Mips::Ulh:
2424 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2425 case Mips::Ulhu:
2426 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002427 case Mips::Ush:
2428 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002429 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002430 case Mips::Usw:
2431 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002432 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002433 case Mips::NORImm64:
2434 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2435 case Mips::SLTImm64:
2436 if (isInt<16>(Inst.getOperand(2).getImm())) {
2437 Inst.setOpcode(Mips::SLTi64);
2438 return MER_NotAMacro;
2439 }
2440 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2441 case Mips::SLTUImm64:
2442 if (isInt<16>(Inst.getOperand(2).getImm())) {
2443 Inst.setOpcode(Mips::SLTiu64);
2444 return MER_NotAMacro;
2445 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002446 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002447 case Mips::ADDi: case Mips::ADDi_MM:
2448 case Mips::ADDiu: case Mips::ADDiu_MM:
2449 case Mips::SLTi: case Mips::SLTi_MM:
2450 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002451 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2452 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2453 int64_t ImmValue = Inst.getOperand(2).getImm();
2454 if (isInt<16>(ImmValue))
2455 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002456 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2457 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002458 }
2459 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002460 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2461 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2462 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002463 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2464 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2465 int64_t ImmValue = Inst.getOperand(2).getImm();
2466 if (isUInt<16>(ImmValue))
2467 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002468 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2469 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002470 }
2471 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002472 case Mips::ROL:
2473 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002474 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002475 case Mips::ROLImm:
2476 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002477 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002478 case Mips::DROL:
2479 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002480 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002481 case Mips::DROLImm:
2482 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002483 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002484 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002485 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002486 case Mips::MULImmMacro:
2487 case Mips::DMULImmMacro:
2488 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2489 case Mips::MULOMacro:
2490 case Mips::DMULOMacro:
2491 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2492 case Mips::MULOUMacro:
2493 case Mips::DMULOUMacro:
2494 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2495 case Mips::DMULMacro:
2496 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002497 case Mips::LDMacro:
2498 case Mips::SDMacro:
2499 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2500 Inst.getOpcode() == Mips::LDMacro)
2501 ? MER_Fail
2502 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002503 case Mips::SEQMacro:
2504 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2505 case Mips::SEQIMacro:
2506 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002507 }
Jack Carter30a59822012-10-04 04:03:53 +00002508}
Jack Carter92995f12012-10-06 00:53:28 +00002509
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002510bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002511 MCStreamer &Out,
2512 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002513 MipsTargetStreamer &TOut = getTargetStreamer();
2514
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002515 // Create a JALR instruction which is going to replace the pseudo-JAL.
2516 MCInst JalrInst;
2517 JalrInst.setLoc(IDLoc);
2518 const MCOperand FirstRegOp = Inst.getOperand(0);
2519 const unsigned Opcode = Inst.getOpcode();
2520
2521 if (Opcode == Mips::JalOneReg) {
2522 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002523 if (IsCpRestoreSet && inMicroMipsMode()) {
2524 JalrInst.setOpcode(Mips::JALRS16_MM);
2525 JalrInst.addOperand(FirstRegOp);
2526 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002527 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002528 JalrInst.addOperand(FirstRegOp);
2529 } else {
2530 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002531 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002532 JalrInst.addOperand(FirstRegOp);
2533 }
2534 } else if (Opcode == Mips::JalTwoReg) {
2535 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002536 if (IsCpRestoreSet && inMicroMipsMode())
2537 JalrInst.setOpcode(Mips::JALRS_MM);
2538 else
2539 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002540 JalrInst.addOperand(FirstRegOp);
2541 const MCOperand SecondRegOp = Inst.getOperand(1);
2542 JalrInst.addOperand(SecondRegOp);
2543 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002544 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002545
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002546 // If .set reorder is active and branch instruction has a delay slot,
2547 // emit a NOP after it.
2548 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002549 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2550 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2551 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002552
2553 return false;
2554}
2555
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002556/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002557template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002558 unsigned BitNum = findFirstSet(x);
2559
2560 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2561}
2562
2563/// Load (or add) an immediate into a register.
2564///
2565/// @param ImmValue The immediate to load.
2566/// @param DstReg The register that will hold the immediate.
2567/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2568/// for a simple initialization.
2569/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2570/// @param IsAddress True if the immediate represents an address. False if it
2571/// is an integer.
2572/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002573bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002574 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002575 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2576 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002577 MipsTargetStreamer &TOut = getTargetStreamer();
2578
Toma Tabacu00e98672015-05-01 12:19:27 +00002579 if (!Is32BitImm && !isGP64bit()) {
2580 Error(IDLoc, "instruction requires a 64-bit architecture");
2581 return true;
2582 }
2583
Daniel Sanders03f9c012015-07-14 12:24:22 +00002584 if (Is32BitImm) {
2585 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2586 // Sign extend up to 64-bit so that the predicates match the hardware
2587 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2588 // true.
2589 ImmValue = SignExtend64<32>(ImmValue);
2590 } else {
2591 Error(IDLoc, "instruction requires a 32-bit immediate");
2592 return true;
2593 }
2594 }
2595
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002596 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2597 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2598
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002599 bool UseSrcReg = false;
2600 if (SrcReg != Mips::NoRegister)
2601 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002602
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002603 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002604 if (UseSrcReg &&
2605 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002606 // At this point we need AT to perform the expansions and we exit if it is
2607 // not available.
2608 unsigned ATReg = getATReg(IDLoc);
2609 if (!ATReg)
2610 return true;
2611 TmpReg = ATReg;
2612 }
2613
Daniel Sanders03f9c012015-07-14 12:24:22 +00002614 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002615 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002616 SrcReg = ZeroReg;
2617
2618 // This doesn't quite follow the usual ABI expectations for N32 but matches
2619 // traditional assembler behaviour. N32 would normally use addiu for both
2620 // integers and addresses.
2621 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002622 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002623 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002624 }
2625
Daniel Sandersa736b372016-04-29 13:33:12 +00002626 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002627 return false;
2628 }
2629
2630 if (isUInt<16>(ImmValue)) {
2631 unsigned TmpReg = DstReg;
2632 if (SrcReg == DstReg) {
2633 TmpReg = getATReg(IDLoc);
2634 if (!TmpReg)
2635 return true;
2636 }
2637
Daniel Sandersa736b372016-04-29 13:33:12 +00002638 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002639 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002640 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002641 return false;
2642 }
2643
2644 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002645 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002646
Toma Tabacu79588102015-04-29 10:19:56 +00002647 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2648 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002649 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002650 // Traditional behaviour seems to special case this particular value. It's
2651 // not clear why other masks are handled differently.
2652 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002653 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2654 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002655 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002656 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002657 return false;
2658 }
2659
2660 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002661 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002662 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2663 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002664 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002665 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002666 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002667 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002668 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002669 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002670
Daniel Sandersa736b372016-04-29 13:33:12 +00002671 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002672 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002673 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002674 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002675 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002676 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002677 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002678
2679 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2680 if (Is32BitImm) {
2681 Error(IDLoc, "instruction requires a 32-bit immediate");
2682 return true;
2683 }
2684
2685 // Traditionally, these immediates are shifted as little as possible and as
2686 // such we align the most significant bit to bit 15 of our temporary.
2687 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2688 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2689 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2690 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002691 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2692 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002693
2694 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002695 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002696
2697 return false;
2698 }
2699
2700 warnIfNoMacro(IDLoc);
2701
2702 // The remaining case is packed with a sequence of dsll and ori with zeros
2703 // being omitted and any neighbouring dsll's being coalesced.
2704 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2705
2706 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2707 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002708 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002709 return false;
2710
2711 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2712 // skip it and defer the shift to the next chunk.
2713 unsigned ShiftCarriedForwards = 16;
2714 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2715 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2716
2717 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002718 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2719 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002720 ShiftCarriedForwards = 0;
2721 }
2722
2723 ShiftCarriedForwards += 16;
2724 }
2725 ShiftCarriedForwards -= 16;
2726
2727 // Finish any remaining shifts left by trailing zeros.
2728 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002729 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002730
2731 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002732 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002733
Matheus Almeida3813d572014-06-19 14:39:14 +00002734 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002735}
Jack Carter92995f12012-10-06 00:53:28 +00002736
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002737bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002738 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002739 const MCOperand &ImmOp = Inst.getOperand(1);
2740 assert(ImmOp.isImm() && "expected immediate operand kind");
2741 const MCOperand &DstRegOp = Inst.getOperand(0);
2742 assert(DstRegOp.isReg() && "expected register operand kind");
2743
2744 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002745 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002746 return true;
2747
2748 return false;
2749}
2750
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002751bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2752 const MCOperand &Offset,
2753 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002754 MCStreamer &Out,
2755 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002756 // la can't produce a usable address when addresses are 64-bit.
2757 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2758 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2759 // We currently can't do this because we depend on the equality
2760 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2761 Error(IDLoc, "la used to load 64-bit address");
2762 // Continue as if we had 'dla' instead.
2763 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002764 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002765 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002766
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002767 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002768 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002769 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002770 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002771 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002772
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002773 if (!Offset.isImm())
2774 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002775 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002776
Scott Egerton24557012016-01-21 15:11:01 +00002777 if (!ABI.ArePtrs64bit()) {
2778 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2779 Is32BitAddress = true;
2780 }
2781
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002782 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002783 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002784}
2785
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002786bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2787 unsigned DstReg, unsigned SrcReg,
2788 bool Is32BitSym, SMLoc IDLoc,
2789 MCStreamer &Out,
2790 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002791 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002792 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002793 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002794
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002795 if (inPicMode() && ABI.IsO32()) {
2796 MCValue Res;
2797 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2798 Error(IDLoc, "expected relocatable expression");
2799 return true;
2800 }
2801 if (Res.getSymB() != nullptr) {
2802 Error(IDLoc, "expected relocatable expression with only one symbol");
2803 return true;
2804 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002805
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002806 // The case where the result register is $25 is somewhat special. If the
2807 // symbol in the final relocation is external and not modified with a
2808 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2809 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2810 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2811 !Res.getSymA()->getSymbol().isTemporary()) {
2812 const MCExpr *CallExpr =
2813 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2814 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2815 MCOperand::createExpr(CallExpr), IDLoc, STI);
2816 return false;
2817 }
2818
2819 // The remaining cases are:
2820 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2821 // >addiu $tmp, $tmp, %lo(offset)
2822 // >addiu $rd, $tmp, $rs
2823 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2824 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2825 // >addiu $rd, $tmp, $rs
2826 // The addiu's marked with a '>' may be omitted if they are redundant. If
2827 // this happens then the last instruction must use $rd as the result
2828 // register.
2829 const MipsMCExpr *GotExpr =
2830 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2831 const MCExpr *LoExpr = nullptr;
2832 if (Res.getSymA()->getSymbol().isInSection() ||
2833 Res.getSymA()->getSymbol().isTemporary())
2834 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2835 else if (Res.getConstant() != 0) {
2836 // External symbols fully resolve the symbol with just the %got(symbol)
2837 // but we must still account for any offset to the symbol for expressions
2838 // like symbol+8.
2839 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2840 }
2841
2842 unsigned TmpReg = DstReg;
2843 if (UseSrcReg &&
2844 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2845 SrcReg)) {
2846 // If $rs is the same as $rd, we need to use AT.
2847 // If it is not available we exit.
2848 unsigned ATReg = getATReg(IDLoc);
2849 if (!ATReg)
2850 return true;
2851 TmpReg = ATReg;
2852 }
2853
2854 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2855 MCOperand::createExpr(GotExpr), IDLoc, STI);
2856
2857 if (LoExpr)
2858 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2859 IDLoc, STI);
2860
2861 if (UseSrcReg)
2862 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2863
2864 return false;
2865 }
2866
2867 const MipsMCExpr *HiExpr =
2868 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2869 const MipsMCExpr *LoExpr =
2870 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002871
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002872 // This is the 64-bit symbol address expansion.
2873 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002874 // We need AT for the 64-bit expansion in the cases where the optional
2875 // source register is the destination register and for the superscalar
2876 // scheduled form.
2877 //
2878 // If it is not available we exit if the destination is the same as the
2879 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002880
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002881 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002882 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002883 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002884 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002885
Simon Dardis3aa8a902017-02-06 12:43:46 +00002886 bool RdRegIsRsReg =
2887 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2888
2889 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2890 unsigned ATReg = getATReg(IDLoc);
2891
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002892 // If $rs is the same as $rd:
2893 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2894 // daddiu $at, $at, %higher(sym)
2895 // dsll $at, $at, 16
2896 // daddiu $at, $at, %hi(sym)
2897 // dsll $at, $at, 16
2898 // daddiu $at, $at, %lo(sym)
2899 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002900 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2901 STI);
2902 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2903 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2904 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2905 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2906 IDLoc, STI);
2907 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2908 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2909 IDLoc, STI);
2910 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002911
2912 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00002913 } else if (canUseATReg() && !RdRegIsRsReg) {
2914 unsigned ATReg = getATReg(IDLoc);
2915
2916 // If the $rs is different from $rd or if $rs isn't specified and we
2917 // have $at available:
2918 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2919 // lui $at, %hi(sym)
2920 // daddiu $rd, $rd, %higher(sym)
2921 // daddiu $at, $at, %lo(sym)
2922 // dsll32 $rd, $rd, 0
2923 // daddu $rd, $rd, $at
2924 // (daddu $rd, $rd, $rs)
2925 //
2926 // Which is preferred for superscalar issue.
2927 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2928 STI);
2929 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2930 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2931 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2932 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2933 IDLoc, STI);
2934 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2935 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
2936 if (UseSrcReg)
2937 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2938
2939 return false;
2940 } else if (!canUseATReg() && !RdRegIsRsReg) {
2941 // Otherwise, synthesize the address in the destination register
2942 // serially:
2943 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2944 // daddiu $rd, $rd, %higher(sym)
2945 // dsll $rd, $rd, 16
2946 // daddiu $rd, $rd, %hi(sym)
2947 // dsll $rd, $rd, 16
2948 // daddiu $rd, $rd, %lo(sym)
2949 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2950 STI);
2951 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2952 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2953 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2954 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2955 MCOperand::createExpr(HiExpr), IDLoc, STI);
2956 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
2957 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2958 MCOperand::createExpr(LoExpr), IDLoc, STI);
2959 if (UseSrcReg)
2960 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
2961
2962 return false;
2963 } else {
2964 // We have a case where SrcReg == DstReg and we don't have $at
2965 // available. We can't expand this case, so error out appropriately.
2966 assert(SrcReg == DstReg && !canUseATReg() &&
2967 "Could have expanded dla but didn't?");
2968 reportParseError(IDLoc,
2969 "pseudo-instruction requires $at, which is not available");
2970 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002971 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002972 }
2973
2974 // And now, the 32-bit symbol address expansion:
2975 // If $rs is the same as $rd:
2976 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2977 // ori $at, $at, %lo(sym)
2978 // addu $rd, $at, $rd
2979 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2980 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2981 // ori $rd, $rd, %lo(sym)
2982 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002983 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002984 if (UseSrcReg &&
2985 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002986 // If $rs is the same as $rd, we need to use AT.
2987 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002988 unsigned ATReg = getATReg(IDLoc);
2989 if (!ATReg)
2990 return true;
2991 TmpReg = ATReg;
2992 }
2993
Daniel Sandersa736b372016-04-29 13:33:12 +00002994 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2995 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2996 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002997
Toma Tabacufb9d1252015-06-22 12:08:39 +00002998 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002999 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003000 else
Scott Egerton24557012016-01-21 15:11:01 +00003001 assert(
3002 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003003
Toma Tabacu674825c2015-06-16 12:16:24 +00003004 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003005}
3006
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003007// Each double-precision register DO-D15 overlaps with two of the single
3008// precision registers F0-F31. As an example, all of the following hold true:
3009// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3010static unsigned nextReg(unsigned Reg) {
3011 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3012 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3013 switch (Reg) {
3014 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3015 case Mips::ZERO: return Mips::AT;
3016 case Mips::AT: return Mips::V0;
3017 case Mips::V0: return Mips::V1;
3018 case Mips::V1: return Mips::A0;
3019 case Mips::A0: return Mips::A1;
3020 case Mips::A1: return Mips::A2;
3021 case Mips::A2: return Mips::A3;
3022 case Mips::A3: return Mips::T0;
3023 case Mips::T0: return Mips::T1;
3024 case Mips::T1: return Mips::T2;
3025 case Mips::T2: return Mips::T3;
3026 case Mips::T3: return Mips::T4;
3027 case Mips::T4: return Mips::T5;
3028 case Mips::T5: return Mips::T6;
3029 case Mips::T6: return Mips::T7;
3030 case Mips::T7: return Mips::S0;
3031 case Mips::S0: return Mips::S1;
3032 case Mips::S1: return Mips::S2;
3033 case Mips::S2: return Mips::S3;
3034 case Mips::S3: return Mips::S4;
3035 case Mips::S4: return Mips::S5;
3036 case Mips::S5: return Mips::S6;
3037 case Mips::S6: return Mips::S7;
3038 case Mips::S7: return Mips::T8;
3039 case Mips::T8: return Mips::T9;
3040 case Mips::T9: return Mips::K0;
3041 case Mips::K0: return Mips::K1;
3042 case Mips::K1: return Mips::GP;
3043 case Mips::GP: return Mips::SP;
3044 case Mips::SP: return Mips::FP;
3045 case Mips::FP: return Mips::RA;
3046 case Mips::RA: return Mips::ZERO;
3047 case Mips::D0: return Mips::F1;
3048 case Mips::D1: return Mips::F3;
3049 case Mips::D2: return Mips::F5;
3050 case Mips::D3: return Mips::F7;
3051 case Mips::D4: return Mips::F9;
3052 case Mips::D5: return Mips::F11;
3053 case Mips::D6: return Mips::F13;
3054 case Mips::D7: return Mips::F15;
3055 case Mips::D8: return Mips::F17;
3056 case Mips::D9: return Mips::F19;
3057 case Mips::D10: return Mips::F21;
3058 case Mips::D11: return Mips::F23;
3059 case Mips::D12: return Mips::F25;
3060 case Mips::D13: return Mips::F27;
3061 case Mips::D14: return Mips::F29;
3062 case Mips::D15: return Mips::F31;
3063 }
3064}
3065
3066// FIXME: This method is too general. In principle we should compute the number
3067// of instructions required to synthesize the immediate inline compared to
3068// synthesizing the address inline and relying on non .text sections.
3069// For static O32 and N32 this may yield a small benefit, for static N64 this is
3070// likely to yield a much larger benefit as we have to synthesize a 64bit
3071// address to load a 64 bit value.
3072bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3073 MCSymbol *Sym) {
3074 unsigned ATReg = getATReg(IDLoc);
3075 if (!ATReg)
3076 return true;
3077
3078 if(IsPicEnabled) {
3079 const MCExpr *GotSym =
3080 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3081 const MipsMCExpr *GotExpr =
3082 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3083
3084 if(isABI_O32() || isABI_N32()) {
3085 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3086 IDLoc, STI);
3087 } else { //isABI_N64()
3088 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3089 IDLoc, STI);
3090 }
3091 } else { //!IsPicEnabled
3092 const MCExpr *HiSym =
3093 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3094 const MipsMCExpr *HiExpr =
3095 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3096
3097 // FIXME: This is technically correct but gives a different result to gas,
3098 // but gas is incomplete there (it has a fixme noting it doesn't work with
3099 // 64-bit addresses).
3100 // FIXME: With -msym32 option, the address expansion for N64 should probably
3101 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3102 // symbol's value is considered sign extended.
3103 if(isABI_O32() || isABI_N32()) {
3104 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3105 } else { //isABI_N64()
3106 const MCExpr *HighestSym =
3107 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3108 const MipsMCExpr *HighestExpr =
3109 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3110 const MCExpr *HigherSym =
3111 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3112 const MipsMCExpr *HigherExpr =
3113 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3114
3115 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3116 STI);
3117 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3118 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3119 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3120 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3121 IDLoc, STI);
3122 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3123 }
3124 }
3125 return false;
3126}
3127
3128bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3129 bool Is64FPU, SMLoc IDLoc,
3130 MCStreamer &Out,
3131 const MCSubtargetInfo *STI) {
3132 MipsTargetStreamer &TOut = getTargetStreamer();
3133 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3134 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3135 "Invalid instruction operand.");
3136
3137 unsigned FirstReg = Inst.getOperand(0).getReg();
3138 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3139
3140 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3141 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3142 // exponent field), convert it to double (e.g. 1 to 1.0)
3143 if ((HiImmOp64 & 0x7ff00000) == 0) {
3144 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3145 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3146 }
3147
3148 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3149 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3150
3151 if (IsSingle) {
3152 // Conversion of a double in an uint64_t to a float in a uint32_t,
3153 // retaining the bit pattern of a float.
3154 uint32_t ImmOp32;
3155 double doubleImm = BitsToDouble(ImmOp64);
3156 float tmp_float = static_cast<float>(doubleImm);
3157 ImmOp32 = FloatToBits(tmp_float);
3158
3159 if (IsGPR) {
3160 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3161 Out, STI))
3162 return true;
3163 return false;
3164 } else {
3165 unsigned ATReg = getATReg(IDLoc);
3166 if (!ATReg)
3167 return true;
3168 if (LoImmOp64 == 0) {
3169 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3170 Out, STI))
3171 return true;
3172 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3173 return false;
3174 }
3175
3176 MCSection *CS = getStreamer().getCurrentSectionOnly();
3177 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3178 // where appropriate.
3179 MCSection *ReadOnlySection = getContext().getELFSection(
3180 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3181
3182 MCSymbol *Sym = getContext().createTempSymbol();
3183 const MCExpr *LoSym =
3184 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3185 const MipsMCExpr *LoExpr =
3186 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3187
3188 getStreamer().SwitchSection(ReadOnlySection);
3189 getStreamer().EmitLabel(Sym, IDLoc);
3190 getStreamer().EmitIntValue(ImmOp32, 4);
3191 getStreamer().SwitchSection(CS);
3192
3193 if(emitPartialAddress(TOut, IDLoc, Sym))
3194 return true;
3195 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3196 MCOperand::createExpr(LoExpr), IDLoc, STI);
3197 }
3198 return false;
3199 }
3200
3201 // if(!IsSingle)
3202 unsigned ATReg = getATReg(IDLoc);
3203 if (!ATReg)
3204 return true;
3205
3206 if (IsGPR) {
3207 if (LoImmOp64 == 0) {
3208 if(isABI_N32() || isABI_N64()) {
3209 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3210 IDLoc, Out, STI))
3211 return true;
3212 return false;
3213 } else {
3214 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3215 IDLoc, Out, STI))
3216 return true;
3217
3218 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3219 IDLoc, Out, STI))
3220 return true;
3221 return false;
3222 }
3223 }
3224
3225 MCSection *CS = getStreamer().getCurrentSectionOnly();
3226 MCSection *ReadOnlySection = getContext().getELFSection(
3227 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3228
3229 MCSymbol *Sym = getContext().createTempSymbol();
3230 const MCExpr *LoSym =
3231 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3232 const MipsMCExpr *LoExpr =
3233 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3234
3235 getStreamer().SwitchSection(ReadOnlySection);
3236 getStreamer().EmitLabel(Sym, IDLoc);
3237 getStreamer().EmitIntValue(HiImmOp64, 4);
3238 getStreamer().EmitIntValue(LoImmOp64, 4);
3239 getStreamer().SwitchSection(CS);
3240
3241 if(emitPartialAddress(TOut, IDLoc, Sym))
3242 return true;
3243 if(isABI_N64())
3244 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3245 MCOperand::createExpr(LoExpr), IDLoc, STI);
3246 else
3247 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3248 MCOperand::createExpr(LoExpr), IDLoc, STI);
3249
3250 if(isABI_N32() || isABI_N64())
3251 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3252 else {
3253 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3254 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3255 }
3256 return false;
3257 } else { // if(!IsGPR && !IsSingle)
3258 if ((LoImmOp64 == 0) &&
3259 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3260 // FIXME: In the case where the constant is zero, we can load the
3261 // register directly from the zero register.
3262 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3263 Out, STI))
3264 return true;
3265 if (isABI_N32() || isABI_N64())
3266 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3267 else if (hasMips32r2()) {
3268 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3269 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3270 } else {
3271 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3272 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3273 }
3274 return false;
3275 }
3276
3277 MCSection *CS = getStreamer().getCurrentSectionOnly();
3278 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3279 // where appropriate.
3280 MCSection *ReadOnlySection = getContext().getELFSection(
3281 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3282
3283 MCSymbol *Sym = getContext().createTempSymbol();
3284 const MCExpr *LoSym =
3285 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3286 const MipsMCExpr *LoExpr =
3287 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3288
3289 getStreamer().SwitchSection(ReadOnlySection);
3290 getStreamer().EmitLabel(Sym, IDLoc);
3291 getStreamer().EmitIntValue(HiImmOp64, 4);
3292 getStreamer().EmitIntValue(LoImmOp64, 4);
3293 getStreamer().SwitchSection(CS);
3294
3295 if(emitPartialAddress(TOut, IDLoc, Sym))
3296 return true;
3297 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3298 MCOperand::createExpr(LoExpr), IDLoc, STI);
3299 }
3300 return false;
3301}
3302
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003303bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3304 MCStreamer &Out,
3305 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003306 MipsTargetStreamer &TOut = getTargetStreamer();
3307
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003308 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3309 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003310
3311 MCOperand Offset = Inst.getOperand(0);
3312 if (Offset.isExpr()) {
3313 Inst.clear();
3314 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003315 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3316 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3317 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003318 } else {
3319 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003320 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003321 // If offset fits into 11 bits then this instruction becomes microMIPS
3322 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003323 if (inMicroMipsMode())
3324 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003325 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003326 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003327 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003328 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003329 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003330 Inst.clear();
3331 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003332 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3333 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3334 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003335 }
3336 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003337 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003338
Zoran Jovanovicada70912015-09-07 11:56:37 +00003339 // If .set reorder is active and branch instruction has a delay slot,
3340 // emit a NOP after it.
3341 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3342 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003343 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003344
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003345 return false;
3346}
3347
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003348bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3349 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003350 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003351 const MCOperand &DstRegOp = Inst.getOperand(0);
3352 assert(DstRegOp.isReg() && "expected register operand kind");
3353
3354 const MCOperand &ImmOp = Inst.getOperand(1);
3355 assert(ImmOp.isImm() && "expected immediate operand kind");
3356
3357 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003358 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3359 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003360
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003361 bool IsLikely = false;
3362
Toma Tabacue1e460d2015-06-11 10:36:10 +00003363 unsigned OpCode = 0;
3364 switch(Inst.getOpcode()) {
3365 case Mips::BneImm:
3366 OpCode = Mips::BNE;
3367 break;
3368 case Mips::BeqImm:
3369 OpCode = Mips::BEQ;
3370 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003371 case Mips::BEQLImmMacro:
3372 OpCode = Mips::BEQL;
3373 IsLikely = true;
3374 break;
3375 case Mips::BNELImmMacro:
3376 OpCode = Mips::BNEL;
3377 IsLikely = true;
3378 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003379 default:
3380 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3381 break;
3382 }
3383
3384 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003385 if (ImmValue == 0) {
3386 if (IsLikely) {
3387 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3388 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3389 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3390 } else
3391 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3392 STI);
3393 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003394 warnIfNoMacro(IDLoc);
3395
3396 unsigned ATReg = getATReg(IDLoc);
3397 if (!ATReg)
3398 return true;
3399
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003400 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003401 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003402 return true;
3403
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003404 if (IsLikely) {
3405 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3406 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3407 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3408 } else
3409 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003410 }
3411 return false;
3412}
3413
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003414void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003415 const MCSubtargetInfo *STI, bool IsLoad,
3416 bool IsImmOpnd) {
3417 if (IsLoad) {
3418 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3419 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003420 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003421 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3422}
3423
3424void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3425 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3426 MipsTargetStreamer &TOut = getTargetStreamer();
3427
3428 unsigned DstReg = Inst.getOperand(0).getReg();
3429 unsigned BaseReg = Inst.getOperand(1).getReg();
3430
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003431 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003432 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3433 unsigned DstRegClassID =
3434 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3435 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3436 (DstRegClassID == Mips::GPR64RegClassID);
3437
3438 if (IsImmOpnd) {
3439 // Try to use DstReg as the temporary.
3440 if (IsGPR && (BaseReg != DstReg)) {
3441 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3442 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3443 STI);
3444 return;
3445 }
3446
Matheus Almeida7de68e72014-06-18 14:46:05 +00003447 // At this point we need AT to perform the expansions and we exit if it is
3448 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003449 unsigned ATReg = getATReg(IDLoc);
3450 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003451 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003452
3453 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3454 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3455 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003456 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003457
Daniel Sandersfba875f2016-04-29 13:43:45 +00003458 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003459 MCOperand LoOperand = MCOperand::createExpr(
3460 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3461 MCOperand HiOperand = MCOperand::createExpr(
3462 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003463
3464 // Try to use DstReg as the temporary.
3465 if (IsGPR && (BaseReg != DstReg)) {
3466 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3467 LoOperand, DstReg, IDLoc, STI);
3468 return;
3469 }
3470
3471 // At this point we need AT to perform the expansions and we exit if it is
3472 // not available.
3473 unsigned ATReg = getATReg(IDLoc);
3474 if (!ATReg)
3475 return;
3476
3477 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3478 LoOperand, ATReg, IDLoc, STI);
3479}
3480
3481void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3482 const MCSubtargetInfo *STI,
3483 bool IsImmOpnd) {
3484 MipsTargetStreamer &TOut = getTargetStreamer();
3485
3486 unsigned SrcReg = Inst.getOperand(0).getReg();
3487 unsigned BaseReg = Inst.getOperand(1).getReg();
3488
Daniel Sanders241c6792016-05-12 14:01:50 +00003489 if (IsImmOpnd) {
3490 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3491 Inst.getOperand(2).getImm(),
3492 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3493 return;
3494 }
3495
Daniel Sandersfba875f2016-04-29 13:43:45 +00003496 unsigned ATReg = getATReg(IDLoc);
3497 if (!ATReg)
3498 return;
3499
Daniel Sandersfba875f2016-04-29 13:43:45 +00003500 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003501 MCOperand LoOperand = MCOperand::createExpr(
3502 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3503 MCOperand HiOperand = MCOperand::createExpr(
3504 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003505 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3506 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003507}
3508
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003509bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3510 MCStreamer &Out,
3511 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003512 unsigned OpNum = Inst.getNumOperands();
3513 unsigned Opcode = Inst.getOpcode();
3514 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3515
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003516 assert(Inst.getOperand(OpNum - 1).isImm() &&
3517 Inst.getOperand(OpNum - 2).isReg() &&
3518 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003519
3520 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3521 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003522 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3523 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3524 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3525 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003526 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003527 if (inMicroMipsMode() && hasMips32r6())
3528 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3529 else
3530 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3531 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003532
3533 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003534 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003535 return false;
3536}
3537
Toma Tabacu1a108322015-06-17 13:20:24 +00003538bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003539 MCStreamer &Out,
3540 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003541 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003542 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003543 unsigned PseudoOpcode = Inst.getOpcode();
3544 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003545 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003546 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3547
3548 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003549 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003550
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003551 unsigned TrgReg;
3552 if (TrgOp.isReg())
3553 TrgReg = TrgOp.getReg();
3554 else if (TrgOp.isImm()) {
3555 warnIfNoMacro(IDLoc);
3556 EmittedNoMacroWarning = true;
3557
3558 TrgReg = getATReg(IDLoc);
3559 if (!TrgReg)
3560 return true;
3561
3562 switch(PseudoOpcode) {
3563 default:
3564 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3565 case Mips::BLTImmMacro:
3566 PseudoOpcode = Mips::BLT;
3567 break;
3568 case Mips::BLEImmMacro:
3569 PseudoOpcode = Mips::BLE;
3570 break;
3571 case Mips::BGEImmMacro:
3572 PseudoOpcode = Mips::BGE;
3573 break;
3574 case Mips::BGTImmMacro:
3575 PseudoOpcode = Mips::BGT;
3576 break;
3577 case Mips::BLTUImmMacro:
3578 PseudoOpcode = Mips::BLTU;
3579 break;
3580 case Mips::BLEUImmMacro:
3581 PseudoOpcode = Mips::BLEU;
3582 break;
3583 case Mips::BGEUImmMacro:
3584 PseudoOpcode = Mips::BGEU;
3585 break;
3586 case Mips::BGTUImmMacro:
3587 PseudoOpcode = Mips::BGTU;
3588 break;
3589 case Mips::BLTLImmMacro:
3590 PseudoOpcode = Mips::BLTL;
3591 break;
3592 case Mips::BLELImmMacro:
3593 PseudoOpcode = Mips::BLEL;
3594 break;
3595 case Mips::BGELImmMacro:
3596 PseudoOpcode = Mips::BGEL;
3597 break;
3598 case Mips::BGTLImmMacro:
3599 PseudoOpcode = Mips::BGTL;
3600 break;
3601 case Mips::BLTULImmMacro:
3602 PseudoOpcode = Mips::BLTUL;
3603 break;
3604 case Mips::BLEULImmMacro:
3605 PseudoOpcode = Mips::BLEUL;
3606 break;
3607 case Mips::BGEULImmMacro:
3608 PseudoOpcode = Mips::BGEUL;
3609 break;
3610 case Mips::BGTULImmMacro:
3611 PseudoOpcode = Mips::BGTUL;
3612 break;
3613 }
3614
3615 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003616 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003617 return true;
3618 }
3619
Toma Tabacu1a108322015-06-17 13:20:24 +00003620 switch (PseudoOpcode) {
3621 case Mips::BLT:
3622 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003623 case Mips::BLTL:
3624 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003625 AcceptsEquality = false;
3626 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003627 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3628 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003629 ZeroSrcOpcode = Mips::BGTZ;
3630 ZeroTrgOpcode = Mips::BLTZ;
3631 break;
3632 case Mips::BLE:
3633 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003634 case Mips::BLEL:
3635 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003636 AcceptsEquality = true;
3637 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003638 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3639 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003640 ZeroSrcOpcode = Mips::BGEZ;
3641 ZeroTrgOpcode = Mips::BLEZ;
3642 break;
3643 case Mips::BGE:
3644 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003645 case Mips::BGEL:
3646 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003647 AcceptsEquality = true;
3648 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003649 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3650 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003651 ZeroSrcOpcode = Mips::BLEZ;
3652 ZeroTrgOpcode = Mips::BGEZ;
3653 break;
3654 case Mips::BGT:
3655 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003656 case Mips::BGTL:
3657 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003658 AcceptsEquality = false;
3659 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003660 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3661 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003662 ZeroSrcOpcode = Mips::BLTZ;
3663 ZeroTrgOpcode = Mips::BGTZ;
3664 break;
3665 default:
3666 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3667 }
3668
Toma Tabacu1a108322015-06-17 13:20:24 +00003669 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3670 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3671 if (IsSrcRegZero && IsTrgRegZero) {
3672 // FIXME: All of these Opcode-specific if's are needed for compatibility
3673 // with GAS' behaviour. However, they may not generate the most efficient
3674 // code in some circumstances.
3675 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003676 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3677 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003678 return false;
3679 }
3680 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003681 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3682 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003683 Warning(IDLoc, "branch is always taken");
3684 return false;
3685 }
3686 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003687 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3688 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003689 Warning(IDLoc, "branch is always taken");
3690 return false;
3691 }
3692 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003693 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3694 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003695 return false;
3696 }
3697 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003698 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3699 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003700 return false;
3701 }
3702 if (AcceptsEquality) {
3703 // If both registers are $0 and the pseudo-branch accepts equality, it
3704 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003705 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3706 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003707 Warning(IDLoc, "branch is always taken");
3708 return false;
3709 }
3710 // If both registers are $0 and the pseudo-branch does not accept
3711 // equality, it will never be taken, so we don't have to emit anything.
3712 return false;
3713 }
3714 if (IsSrcRegZero || IsTrgRegZero) {
3715 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3716 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3717 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3718 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3719 // the pseudo-branch will never be taken, so we don't emit anything.
3720 // This only applies to unsigned pseudo-branches.
3721 return false;
3722 }
3723 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3724 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3725 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3726 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3727 // the pseudo-branch will always be taken, so we emit an unconditional
3728 // branch.
3729 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003730 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3731 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003732 Warning(IDLoc, "branch is always taken");
3733 return false;
3734 }
3735 if (IsUnsigned) {
3736 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3737 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3738 // the pseudo-branch will be taken only when the non-zero register is
3739 // different from 0, so we emit a BNEZ.
3740 //
3741 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3742 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3743 // the pseudo-branch will be taken only when the non-zero register is
3744 // equal to 0, so we emit a BEQZ.
3745 //
3746 // Because only BLEU and BGEU branch on equality, we can use the
3747 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003748 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3749 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3750 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003751 return false;
3752 }
3753 // If we have a signed pseudo-branch and one of the registers is $0,
3754 // we can use an appropriate compare-to-zero branch. We select which one
3755 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003756 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3757 IsSrcRegZero ? TrgReg : SrcReg,
3758 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003759 return false;
3760 }
3761
3762 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3763 // expansions. If it is not available, we return.
3764 unsigned ATRegNum = getATReg(IDLoc);
3765 if (!ATRegNum)
3766 return true;
3767
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003768 if (!EmittedNoMacroWarning)
3769 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003770
3771 // SLT fits well with 2 of our 4 pseudo-branches:
3772 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3773 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3774 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3775 // This is accomplished by using a BNEZ with the result of the SLT.
3776 //
3777 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3778 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3779 // Because only BGE and BLE branch on equality, we can use the
3780 // AcceptsEquality variable to decide when to emit the BEQZ.
3781 // Note that the order of the SLT arguments doesn't change between
3782 // opposites.
3783 //
3784 // The same applies to the unsigned variants, except that SLTu is used
3785 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003786 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3787 ReverseOrderSLT ? TrgReg : SrcReg,
3788 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003789
Daniel Sandersa736b372016-04-29 13:33:12 +00003790 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3791 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3792 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3793 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003794 return false;
3795}
3796
Simon Dardis509da1a2017-02-13 16:06:48 +00003797// Expand a integer division macro.
3798//
3799// Notably we don't have to emit a warning when encountering $rt as the $zero
3800// register, or 0 as an immediate. processInstruction() has already done that.
3801//
3802// The destination register can only be $zero when expanding (S)DivIMacro or
3803// D(S)DivMacro.
3804
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003805bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3806 const MCSubtargetInfo *STI, const bool IsMips64,
3807 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003808 MipsTargetStreamer &TOut = getTargetStreamer();
3809
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003810 warnIfNoMacro(IDLoc);
3811
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003812 const MCOperand &RdRegOp = Inst.getOperand(0);
3813 assert(RdRegOp.isReg() && "expected register operand kind");
3814 unsigned RdReg = RdRegOp.getReg();
3815
3816 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003817 assert(RsRegOp.isReg() && "expected register operand kind");
3818 unsigned RsReg = RsRegOp.getReg();
3819
Simon Dardis12850ee2017-01-31 10:49:24 +00003820 unsigned RtReg;
3821 int64_t ImmValue;
3822
3823 const MCOperand &RtOp = Inst.getOperand(2);
3824 assert((RtOp.isReg() || RtOp.isImm()) &&
3825 "expected register or immediate operand kind");
3826 if (RtOp.isReg())
3827 RtReg = RtOp.getReg();
3828 else
3829 ImmValue = RtOp.getImm();
3830
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003831 unsigned DivOp;
3832 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003833 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003834
3835 if (IsMips64) {
3836 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3837 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003838 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003839 } else {
3840 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3841 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003842 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003843 }
3844
3845 bool UseTraps = useTraps();
3846
Simon Dardis12850ee2017-01-31 10:49:24 +00003847 if (RtOp.isImm()) {
3848 unsigned ATReg = getATReg(IDLoc);
3849 if (!ATReg)
3850 return true;
3851
3852 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003853 if (UseTraps)
3854 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3855 else
3856 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3857 return false;
3858 }
3859
3860 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003861 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003862 return false;
3863 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003864 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003865 return false;
3866 } else {
3867 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3868 false, Inst.getLoc(), Out, STI))
3869 return true;
3870 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3871 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3872 return false;
3873 }
3874 return true;
3875 }
3876
Simon Dardis509da1a2017-02-13 16:06:48 +00003877 // If the macro expansion of (d)div(u) would always trap or break, insert
3878 // the trap/break and exit. This gives a different result to GAS. GAS has
3879 // an inconsistency/missed optimization in that not all cases are handled
3880 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003881 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003882 if (UseTraps) {
3883 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003884 return false;
3885 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003886 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3887 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003888 }
3889
Simon Dardis509da1a2017-02-13 16:06:48 +00003890 // Temporary label for first branch traget
3891 MCContext &Context = TOut.getStreamer().getContext();
3892 MCSymbol *BrTarget;
3893 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003894
3895 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003896 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003897 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003898 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003899 BrTarget = Context.createTempSymbol();
3900 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
3901 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003902 }
3903
Daniel Sandersa736b372016-04-29 13:33:12 +00003904 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003905
3906 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003907 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003908
3909 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003910 if (!UseTraps)
3911 TOut.getStreamer().EmitLabel(BrTarget);
3912
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003913 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003914 return false;
3915 }
3916
3917 unsigned ATReg = getATReg(IDLoc);
3918 if (!ATReg)
3919 return true;
3920
Simon Dardis509da1a2017-02-13 16:06:48 +00003921 if (!UseTraps)
3922 TOut.getStreamer().EmitLabel(BrTarget);
3923
Daniel Sandersa736b372016-04-29 13:33:12 +00003924 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00003925
3926 // Temporary label for the second branch target.
3927 MCSymbol *BrTargetEnd = Context.createTempSymbol();
3928 MCOperand LabelOpEnd =
3929 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
3930
3931 // Branch to the mflo instruction.
3932 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
3933
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003934 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003935 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3936 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003937 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003938 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003939 }
3940
3941 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003942 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003943 else {
3944 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003945 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003946 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3947 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003948 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003949
3950 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003951 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003952 return false;
3953}
3954
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003955bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003956 SMLoc IDLoc, MCStreamer &Out,
3957 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003958 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003959
3960 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3961 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3962 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3963
3964 unsigned FirstReg = Inst.getOperand(0).getReg();
3965 unsigned SecondReg = Inst.getOperand(1).getReg();
3966 unsigned ThirdReg = Inst.getOperand(2).getReg();
3967
3968 if (hasMips1() && !hasMips2()) {
3969 unsigned ATReg = getATReg(IDLoc);
3970 if (!ATReg)
3971 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003972 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3973 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3974 TOut.emitNop(IDLoc, STI);
3975 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3976 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3977 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3978 TOut.emitNop(IDLoc, STI);
3979 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3980 : Mips::CVT_W_S,
3981 FirstReg, SecondReg, IDLoc, STI);
3982 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3983 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003984 return false;
3985 }
3986
Daniel Sandersa736b372016-04-29 13:33:12 +00003987 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3988 : Mips::TRUNC_W_S,
3989 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003990
3991 return false;
3992}
3993
Daniel Sanders6394ee52015-10-15 14:52:58 +00003994bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003995 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003996 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003997 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003998 }
3999
Toma Tabacud88d79c2015-06-23 14:39:42 +00004000 const MCOperand &DstRegOp = Inst.getOperand(0);
4001 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004002 const MCOperand &SrcRegOp = Inst.getOperand(1);
4003 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004004 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4005 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4006
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004007 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004008 unsigned DstReg = DstRegOp.getReg();
4009 unsigned SrcReg = SrcRegOp.getReg();
4010 int64_t OffsetValue = OffsetImmOp.getImm();
4011
4012 // NOTE: We always need AT for ULHU, as it is always used as the source
4013 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004014 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004015 unsigned ATReg = getATReg(IDLoc);
4016 if (!ATReg)
4017 return true;
4018
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004019 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4020 if (IsLargeOffset) {
4021 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4022 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004023 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004024 }
4025
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004026 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4027 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4028 if (isLittle())
4029 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004030
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004031 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4032 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004033
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004034 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4035 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004036
Daniel Sandersa736b372016-04-29 13:33:12 +00004037 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004038 FirstOffset, IDLoc, STI);
4039 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004040 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004041 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004042
4043 return false;
4044}
4045
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004046bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004047 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004048 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004049 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004050 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004051
4052 const MCOperand &DstRegOp = Inst.getOperand(0);
4053 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004054 const MCOperand &SrcRegOp = Inst.getOperand(1);
4055 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004056 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4057 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4058
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004059 MipsTargetStreamer &TOut = getTargetStreamer();
4060 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004061 unsigned SrcReg = SrcRegOp.getReg();
4062 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004063
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004064 warnIfNoMacro(IDLoc);
4065 unsigned ATReg = getATReg(IDLoc);
4066 if (!ATReg)
4067 return true;
4068
4069 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4070 if (IsLargeOffset) {
4071 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4072 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004073 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004074 }
4075
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004076 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4077 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4078 if (isLittle())
4079 std::swap(FirstOffset, SecondOffset);
4080
4081 if (IsLargeOffset) {
4082 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4083 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4084 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4085 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4086 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4087 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004088 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004089 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4090 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4091 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004092 }
4093
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004094 return false;
4095}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004096
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004097bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4098 const MCSubtargetInfo *STI) {
4099 if (hasMips32r6() || hasMips64r6()) {
4100 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4101 }
4102
4103 const MCOperand &DstRegOp = Inst.getOperand(0);
4104 assert(DstRegOp.isReg() && "expected register operand kind");
4105 const MCOperand &SrcRegOp = Inst.getOperand(1);
4106 assert(SrcRegOp.isReg() && "expected register operand kind");
4107 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4108 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4109
4110 MipsTargetStreamer &TOut = getTargetStreamer();
4111 unsigned DstReg = DstRegOp.getReg();
4112 unsigned SrcReg = SrcRegOp.getReg();
4113 int64_t OffsetValue = OffsetImmOp.getImm();
4114
4115 // Compute left/right load/store offsets.
4116 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4117 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4118 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4119 if (isLittle())
4120 std::swap(LxlOffset, LxrOffset);
4121
4122 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4123 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4124 unsigned TmpReg = SrcReg;
4125 if (IsLargeOffset || DoMove) {
4126 warnIfNoMacro(IDLoc);
4127 TmpReg = getATReg(IDLoc);
4128 if (!TmpReg)
4129 return true;
4130 }
4131
4132 if (IsLargeOffset) {
4133 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4134 IDLoc, Out, STI))
4135 return true;
4136 }
4137
4138 if (DoMove)
4139 std::swap(DstReg, TmpReg);
4140
4141 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4142 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4143 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4144 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4145
4146 if (DoMove)
4147 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004148
4149 return false;
4150}
4151
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004152bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004153 MCStreamer &Out,
4154 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004155 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004156
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004157 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4158 assert(Inst.getOperand(0).isReg() &&
4159 Inst.getOperand(1).isReg() &&
4160 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004161
4162 unsigned ATReg = Mips::NoRegister;
4163 unsigned FinalDstReg = Mips::NoRegister;
4164 unsigned DstReg = Inst.getOperand(0).getReg();
4165 unsigned SrcReg = Inst.getOperand(1).getReg();
4166 int64_t ImmValue = Inst.getOperand(2).getImm();
4167
Simon Dardisaa208812017-02-24 14:34:32 +00004168 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004169
4170 unsigned FinalOpcode = Inst.getOpcode();
4171
4172 if (DstReg == SrcReg) {
4173 ATReg = getATReg(Inst.getLoc());
4174 if (!ATReg)
4175 return true;
4176 FinalDstReg = DstReg;
4177 DstReg = ATReg;
4178 }
4179
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004180 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004181 switch (FinalOpcode) {
4182 default:
4183 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004184 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004185 FinalOpcode = Mips::ADD;
4186 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004187 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004188 FinalOpcode = Mips::ADDu;
4189 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004190 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004191 FinalOpcode = Mips::AND;
4192 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004193 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004194 FinalOpcode = Mips::NOR;
4195 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004196 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004197 FinalOpcode = Mips::OR;
4198 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004199 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004200 FinalOpcode = Mips::SLT;
4201 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004202 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004203 FinalOpcode = Mips::SLTu;
4204 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004205 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004206 FinalOpcode = Mips::XOR;
4207 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004208 case Mips::ADDi_MM:
4209 FinalOpcode = Mips::ADD_MM;
4210 break;
4211 case Mips::ADDiu_MM:
4212 FinalOpcode = Mips::ADDu_MM;
4213 break;
4214 case Mips::ANDi_MM:
4215 FinalOpcode = Mips::AND_MM;
4216 break;
4217 case Mips::ORi_MM:
4218 FinalOpcode = Mips::OR_MM;
4219 break;
4220 case Mips::SLTi_MM:
4221 FinalOpcode = Mips::SLT_MM;
4222 break;
4223 case Mips::SLTiu_MM:
4224 FinalOpcode = Mips::SLTu_MM;
4225 break;
4226 case Mips::XORi_MM:
4227 FinalOpcode = Mips::XOR_MM;
4228 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004229 case Mips::ANDi64:
4230 FinalOpcode = Mips::AND64;
4231 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004232 case Mips::NORImm64:
4233 FinalOpcode = Mips::NOR64;
4234 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004235 case Mips::ORi64:
4236 FinalOpcode = Mips::OR64;
4237 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004238 case Mips::SLTImm64:
4239 FinalOpcode = Mips::SLT64;
4240 break;
4241 case Mips::SLTUImm64:
4242 FinalOpcode = Mips::SLTu64;
4243 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004244 case Mips::XORi64:
4245 FinalOpcode = Mips::XOR64;
4246 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004247 }
4248
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004249 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004250 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004251 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004252 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004253 return false;
4254 }
4255 return true;
4256}
4257
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004258bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4259 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004260 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004261 unsigned ATReg = Mips::NoRegister;
4262 unsigned DReg = Inst.getOperand(0).getReg();
4263 unsigned SReg = Inst.getOperand(1).getReg();
4264 unsigned TReg = Inst.getOperand(2).getReg();
4265 unsigned TmpReg = DReg;
4266
4267 unsigned FirstShift = Mips::NOP;
4268 unsigned SecondShift = Mips::NOP;
4269
4270 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004271 if (DReg == SReg) {
4272 TmpReg = getATReg(Inst.getLoc());
4273 if (!TmpReg)
4274 return true;
4275 }
4276
4277 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004278 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4279 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004280 return false;
4281 }
4282
4283 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004284 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004285 return false;
4286 }
4287
4288 return true;
4289 }
4290
4291 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004292 switch (Inst.getOpcode()) {
4293 default:
4294 llvm_unreachable("unexpected instruction opcode");
4295 case Mips::ROL:
4296 FirstShift = Mips::SRLV;
4297 SecondShift = Mips::SLLV;
4298 break;
4299 case Mips::ROR:
4300 FirstShift = Mips::SLLV;
4301 SecondShift = Mips::SRLV;
4302 break;
4303 }
4304
4305 ATReg = getATReg(Inst.getLoc());
4306 if (!ATReg)
4307 return true;
4308
Daniel Sandersa736b372016-04-29 13:33:12 +00004309 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4310 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4311 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4312 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004313
4314 return false;
4315 }
4316
4317 return true;
4318}
4319
4320bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004321 MCStreamer &Out,
4322 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004323 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004324 unsigned ATReg = Mips::NoRegister;
4325 unsigned DReg = Inst.getOperand(0).getReg();
4326 unsigned SReg = Inst.getOperand(1).getReg();
4327 int64_t ImmValue = Inst.getOperand(2).getImm();
4328
4329 unsigned FirstShift = Mips::NOP;
4330 unsigned SecondShift = Mips::NOP;
4331
4332 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004333 if (Inst.getOpcode() == Mips::ROLImm) {
4334 uint64_t MaxShift = 32;
4335 uint64_t ShiftValue = ImmValue;
4336 if (ImmValue != 0)
4337 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004338 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004339 return false;
4340 }
4341
4342 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004343 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004344 return false;
4345 }
4346
4347 return true;
4348 }
4349
4350 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004351 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004352 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004353 return false;
4354 }
4355
4356 switch (Inst.getOpcode()) {
4357 default:
4358 llvm_unreachable("unexpected instruction opcode");
4359 case Mips::ROLImm:
4360 FirstShift = Mips::SLL;
4361 SecondShift = Mips::SRL;
4362 break;
4363 case Mips::RORImm:
4364 FirstShift = Mips::SRL;
4365 SecondShift = Mips::SLL;
4366 break;
4367 }
4368
4369 ATReg = getATReg(Inst.getLoc());
4370 if (!ATReg)
4371 return true;
4372
Daniel Sandersa736b372016-04-29 13:33:12 +00004373 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4374 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4375 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004376
4377 return false;
4378 }
4379
4380 return true;
4381}
4382
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004383bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4384 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004385 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004386 unsigned ATReg = Mips::NoRegister;
4387 unsigned DReg = Inst.getOperand(0).getReg();
4388 unsigned SReg = Inst.getOperand(1).getReg();
4389 unsigned TReg = Inst.getOperand(2).getReg();
4390 unsigned TmpReg = DReg;
4391
4392 unsigned FirstShift = Mips::NOP;
4393 unsigned SecondShift = Mips::NOP;
4394
4395 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004396 if (TmpReg == SReg) {
4397 TmpReg = getATReg(Inst.getLoc());
4398 if (!TmpReg)
4399 return true;
4400 }
4401
4402 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004403 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4404 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004405 return false;
4406 }
4407
4408 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004409 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004410 return false;
4411 }
4412
4413 return true;
4414 }
4415
4416 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004417 switch (Inst.getOpcode()) {
4418 default:
4419 llvm_unreachable("unexpected instruction opcode");
4420 case Mips::DROL:
4421 FirstShift = Mips::DSRLV;
4422 SecondShift = Mips::DSLLV;
4423 break;
4424 case Mips::DROR:
4425 FirstShift = Mips::DSLLV;
4426 SecondShift = Mips::DSRLV;
4427 break;
4428 }
4429
4430 ATReg = getATReg(Inst.getLoc());
4431 if (!ATReg)
4432 return true;
4433
Daniel Sandersa736b372016-04-29 13:33:12 +00004434 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4435 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4436 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4437 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004438
4439 return false;
4440 }
4441
4442 return true;
4443}
4444
4445bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004446 MCStreamer &Out,
4447 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004448 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004449 unsigned ATReg = Mips::NoRegister;
4450 unsigned DReg = Inst.getOperand(0).getReg();
4451 unsigned SReg = Inst.getOperand(1).getReg();
4452 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4453
4454 unsigned FirstShift = Mips::NOP;
4455 unsigned SecondShift = Mips::NOP;
4456
4457 MCInst TmpInst;
4458
4459 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004460 unsigned FinalOpcode = Mips::NOP;
4461 if (ImmValue == 0)
4462 FinalOpcode = Mips::DROTR;
4463 else if (ImmValue % 32 == 0)
4464 FinalOpcode = Mips::DROTR32;
4465 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4466 if (Inst.getOpcode() == Mips::DROLImm)
4467 FinalOpcode = Mips::DROTR32;
4468 else
4469 FinalOpcode = Mips::DROTR;
4470 } else if (ImmValue >= 33) {
4471 if (Inst.getOpcode() == Mips::DROLImm)
4472 FinalOpcode = Mips::DROTR;
4473 else
4474 FinalOpcode = Mips::DROTR32;
4475 }
4476
4477 uint64_t ShiftValue = ImmValue % 32;
4478 if (Inst.getOpcode() == Mips::DROLImm)
4479 ShiftValue = (32 - ImmValue % 32) % 32;
4480
Daniel Sandersa736b372016-04-29 13:33:12 +00004481 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004482
4483 return false;
4484 }
4485
4486 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004487 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004488 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004489 return false;
4490 }
4491
4492 switch (Inst.getOpcode()) {
4493 default:
4494 llvm_unreachable("unexpected instruction opcode");
4495 case Mips::DROLImm:
4496 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4497 FirstShift = Mips::DSLL;
4498 SecondShift = Mips::DSRL32;
4499 }
4500 if (ImmValue == 32) {
4501 FirstShift = Mips::DSLL32;
4502 SecondShift = Mips::DSRL32;
4503 }
4504 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4505 FirstShift = Mips::DSLL32;
4506 SecondShift = Mips::DSRL;
4507 }
4508 break;
4509 case Mips::DRORImm:
4510 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4511 FirstShift = Mips::DSRL;
4512 SecondShift = Mips::DSLL32;
4513 }
4514 if (ImmValue == 32) {
4515 FirstShift = Mips::DSRL32;
4516 SecondShift = Mips::DSLL32;
4517 }
4518 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4519 FirstShift = Mips::DSRL32;
4520 SecondShift = Mips::DSLL;
4521 }
4522 break;
4523 }
4524
4525 ATReg = getATReg(Inst.getLoc());
4526 if (!ATReg)
4527 return true;
4528
Daniel Sandersa736b372016-04-29 13:33:12 +00004529 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4530 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4531 Inst.getLoc(), STI);
4532 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004533
4534 return false;
4535 }
4536
4537 return true;
4538}
4539
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004540bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4541 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004542 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004543 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4544 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4545
Daniel Sandersa736b372016-04-29 13:33:12 +00004546 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004547 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004548 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004549 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004550 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4551 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004552
4553 return false;
4554}
4555
Simon Dardis3c82a642017-02-08 16:25:05 +00004556bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4557 const MCSubtargetInfo *STI) {
4558 MipsTargetStreamer &TOut = getTargetStreamer();
4559 unsigned ATReg = Mips::NoRegister;
4560 unsigned DstReg = Inst.getOperand(0).getReg();
4561 unsigned SrcReg = Inst.getOperand(1).getReg();
4562 int32_t ImmValue = Inst.getOperand(2).getImm();
4563
4564 ATReg = getATReg(IDLoc);
4565 if (!ATReg)
4566 return true;
4567
4568 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4569
4570 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4571 SrcReg, ATReg, IDLoc, STI);
4572
4573 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4574
4575 return false;
4576}
4577
4578bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4579 const MCSubtargetInfo *STI) {
4580 MipsTargetStreamer &TOut = getTargetStreamer();
4581 unsigned ATReg = Mips::NoRegister;
4582 unsigned DstReg = Inst.getOperand(0).getReg();
4583 unsigned SrcReg = Inst.getOperand(1).getReg();
4584 unsigned TmpReg = Inst.getOperand(2).getReg();
4585
4586 ATReg = getATReg(Inst.getLoc());
4587 if (!ATReg)
4588 return true;
4589
4590 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4591 SrcReg, TmpReg, IDLoc, STI);
4592
4593 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4594
4595 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4596 DstReg, DstReg, 0x1F, IDLoc, STI);
4597
4598 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4599
4600 if (useTraps()) {
4601 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4602 } else {
4603 MCContext & Context = TOut.getStreamer().getContext();
4604 MCSymbol * BrTarget = Context.createTempSymbol();
4605 MCOperand LabelOp =
4606 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4607
4608 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4609 if (AssemblerOptions.back()->isReorder())
4610 TOut.emitNop(IDLoc, STI);
4611 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4612
4613 TOut.getStreamer().EmitLabel(BrTarget);
4614 }
4615 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4616
4617 return false;
4618}
4619
4620bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4621 const MCSubtargetInfo *STI) {
4622 MipsTargetStreamer &TOut = getTargetStreamer();
4623 unsigned ATReg = Mips::NoRegister;
4624 unsigned DstReg = Inst.getOperand(0).getReg();
4625 unsigned SrcReg = Inst.getOperand(1).getReg();
4626 unsigned TmpReg = Inst.getOperand(2).getReg();
4627
4628 ATReg = getATReg(IDLoc);
4629 if (!ATReg)
4630 return true;
4631
4632 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4633 SrcReg, TmpReg, IDLoc, STI);
4634
4635 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4636 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4637 if (useTraps()) {
4638 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4639 } else {
4640 MCContext & Context = TOut.getStreamer().getContext();
4641 MCSymbol * BrTarget = Context.createTempSymbol();
4642 MCOperand LabelOp =
4643 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4644
4645 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4646 if (AssemblerOptions.back()->isReorder())
4647 TOut.emitNop(IDLoc, STI);
4648 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4649
4650 TOut.getStreamer().EmitLabel(BrTarget);
4651 }
4652
4653 return false;
4654}
4655
4656bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4657 const MCSubtargetInfo *STI) {
4658 MipsTargetStreamer &TOut = getTargetStreamer();
4659 unsigned DstReg = Inst.getOperand(0).getReg();
4660 unsigned SrcReg = Inst.getOperand(1).getReg();
4661 unsigned TmpReg = Inst.getOperand(2).getReg();
4662
4663 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4664 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4665
4666 return false;
4667}
4668
Simon Dardisaff4d142016-10-18 14:28:00 +00004669// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4670// lw $<reg+1>>, offset+4($reg2)'
4671// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4672// sw $<reg+1>>, offset+4($reg2)'
4673// for O32.
4674bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4675 MCStreamer &Out,
4676 const MCSubtargetInfo *STI,
4677 bool IsLoad) {
4678 if (!isABI_O32())
4679 return true;
4680
4681 warnIfNoMacro(IDLoc);
4682
4683 MipsTargetStreamer &TOut = getTargetStreamer();
4684 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4685 unsigned FirstReg = Inst.getOperand(0).getReg();
4686 unsigned SecondReg = nextReg(FirstReg);
4687 unsigned BaseReg = Inst.getOperand(1).getReg();
4688 if (!SecondReg)
4689 return true;
4690
4691 warnIfRegIndexIsAT(FirstReg, IDLoc);
4692
4693 assert(Inst.getOperand(2).isImm() &&
4694 "Offset for load macro is not immediate!");
4695
4696 MCOperand &FirstOffset = Inst.getOperand(2);
4697 signed NextOffset = FirstOffset.getImm() + 4;
4698 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4699
4700 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4701 return true;
4702
4703 // For loads, clobber the base register with the second load instead of the
4704 // first if the BaseReg == FirstReg.
4705 if (FirstReg != BaseReg || !IsLoad) {
4706 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4707 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4708 } else {
4709 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4710 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4711 }
4712
4713 return false;
4714}
4715
Simon Dardis43115a12016-11-21 20:30:41 +00004716bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4717 const MCSubtargetInfo *STI) {
4718
4719 warnIfNoMacro(IDLoc);
4720 MipsTargetStreamer &TOut = getTargetStreamer();
4721
4722 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4723 Inst.getOperand(2).getReg() != Mips::ZERO) {
4724 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4725 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4726 IDLoc, STI);
4727 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4728 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4729 return false;
4730 }
4731
4732 unsigned Reg = 0;
4733 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4734 Reg = Inst.getOperand(2).getReg();
4735 } else {
4736 Reg = Inst.getOperand(1).getReg();
4737 }
4738 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4739 return false;
4740}
4741
4742bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4743 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004744 warnIfNoMacro(IDLoc);
4745 MipsTargetStreamer &TOut = getTargetStreamer();
4746
4747 unsigned Opc;
4748 int64_t Imm = Inst.getOperand(2).getImm();
4749 unsigned Reg = Inst.getOperand(1).getReg();
4750
4751 if (Imm == 0) {
4752 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4753 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4754 return false;
4755 } else {
4756
4757 if (Reg == Mips::ZERO) {
4758 Warning(IDLoc, "comparison is always false");
4759 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4760 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4761 return false;
4762 }
4763
4764 if (Imm > -0x8000 && Imm < 0) {
4765 Imm = -Imm;
4766 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4767 } else {
4768 Opc = Mips::XORi;
4769 }
4770 }
4771 if (!isUInt<16>(Imm)) {
4772 unsigned ATReg = getATReg(IDLoc);
4773 if (!ATReg)
4774 return true;
4775
4776 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4777 Out, STI))
4778 return true;
4779
4780 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4781 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4782 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4783 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4784 return false;
4785 }
4786
4787 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4788 Imm, IDLoc, STI);
4789 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4790 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4791 return false;
4792}
4793
Daniel Sandersc5537422016-07-27 13:49:44 +00004794unsigned
4795MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4796 const OperandVector &Operands) {
4797 switch (Inst.getOpcode()) {
4798 default:
4799 return Match_Success;
4800 case Mips::DATI:
4801 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004802 case Mips::DATI_MM64R6:
4803 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004804 if (static_cast<MipsOperand &>(*Operands[1])
4805 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4806 return Match_Success;
4807 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004808 }
4809}
Simon Dardis730fdb72017-01-16 13:55:58 +00004810
Matheus Almeida595fcab2014-06-11 15:05:56 +00004811unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004812 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004813 // As described by the MIPSR6 spec, daui must not use the zero operand for
4814 // its source operand.
4815 case Mips::DAUI:
4816 case Mips::DAUI_MM64R6:
4817 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4818 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4819 return Match_RequiresNoZeroRegister;
4820 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004821 // As described by the Mips32r2 spec, the registers Rd and Rs for
4822 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004823 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004824 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004825 case Mips::JALR_HB:
4826 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004827 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004828 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4829 return Match_RequiresDifferentSrcAndDst;
4830 return Match_Success;
4831 case Mips::LWP_MM:
4832 case Mips::LWP_MMR6:
4833 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4834 return Match_RequiresDifferentSrcAndDst;
4835 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004836 case Mips::SYNC:
4837 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4838 return Match_NonZeroOperandForSync;
4839 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004840 // As described the MIPSR6 spec, the compact branches that compare registers
4841 // must:
4842 // a) Not use the zero register.
4843 // b) Not use the same register twice.
4844 // c) rs < rt for bnec, beqc.
4845 // NB: For this case, the encoding will swap the operands as their
4846 // ordering doesn't matter. GAS performs this transformation too.
4847 // Hence, that constraint does not have to be enforced.
4848 //
4849 // The compact branches that branch iff the signed addition of two registers
4850 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4851 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004852 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4853 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4854 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4855 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4856 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4857 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004858 case Mips::BLEZC64:
4859 case Mips::BGEZC64:
4860 case Mips::BGTZC64:
4861 case Mips::BLTZC64:
4862 case Mips::BEQZC64:
4863 case Mips::BNEZC64:
4864 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4865 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004866 return Match_RequiresNoZeroRegister;
4867 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004868 case Mips::BGEC: case Mips::BGEC_MMR6:
4869 case Mips::BLTC: case Mips::BLTC_MMR6:
4870 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4871 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4872 case Mips::BEQC: case Mips::BEQC_MMR6:
4873 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004874 case Mips::BGEC64:
4875 case Mips::BLTC64:
4876 case Mips::BGEUC64:
4877 case Mips::BLTUC64:
4878 case Mips::BEQC64:
4879 case Mips::BNEC64:
4880 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4881 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004882 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004883 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4884 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004885 return Match_RequiresNoZeroRegister;
4886 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4887 return Match_RequiresDifferentOperands;
4888 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004889 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004890
4891 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4892 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4893 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4894 return Match_NoFCCRegisterForCurrentISA;
4895
4896 return Match_Success;
4897
Matheus Almeida595fcab2014-06-11 15:05:56 +00004898}
4899
Daniel Sanders52da7af2015-11-06 12:11:03 +00004900static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4901 uint64_t ErrorInfo) {
4902 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4903 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4904 if (ErrorLoc == SMLoc())
4905 return Loc;
4906 return ErrorLoc;
4907 }
4908 return Loc;
4909}
4910
David Blaikie960ea3f2014-06-08 16:18:35 +00004911bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4912 OperandVector &Operands,
4913 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004914 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004915 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004916 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004917 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004918 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004919
4920 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004921 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004922 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004923 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004924 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00004925 case Match_MissingFeature:
4926 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4927 return true;
4928 case Match_InvalidOperand: {
4929 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004930 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004931 if (ErrorInfo >= Operands.size())
4932 return Error(IDLoc, "too few operands for instruction");
4933
Daniel Sanders52da7af2015-11-06 12:11:03 +00004934 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004935 if (ErrorLoc == SMLoc())
4936 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004937 }
4938
4939 return Error(ErrorLoc, "invalid operand for instruction");
4940 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004941 case Match_NonZeroOperandForSync:
4942 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004943 case Match_MnemonicFail:
4944 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004945 case Match_RequiresDifferentSrcAndDst:
4946 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004947 case Match_RequiresDifferentOperands:
4948 return Error(IDLoc, "registers must be different");
4949 case Match_RequiresNoZeroRegister:
4950 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004951 case Match_RequiresSameSrcAndDst:
4952 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00004953 case Match_NoFCCRegisterForCurrentISA:
4954 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4955 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004956 case Match_Immz:
4957 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004958 case Match_UImm1_0:
4959 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4960 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004961 case Match_UImm2_0:
4962 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4963 "expected 2-bit unsigned immediate");
4964 case Match_UImm2_1:
4965 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4966 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004967 case Match_UImm3_0:
4968 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4969 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004970 case Match_UImm4_0:
4971 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4972 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004973 case Match_SImm4_0:
4974 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4975 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004976 case Match_UImm5_0:
4977 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4978 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004979 case Match_SImm5_0:
4980 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4981 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004982 case Match_UImm5_1:
4983 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4984 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004985 case Match_UImm5_32:
4986 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4987 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004988 case Match_UImm5_33:
4989 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4990 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004991 case Match_UImm5_0_Report_UImm6:
4992 // This is used on UImm5 operands that have a corresponding UImm5_32
4993 // operand to avoid confusing the user.
4994 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4995 "expected 6-bit unsigned immediate");
4996 case Match_UImm5_Lsl2:
4997 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4998 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004999 case Match_UImmRange2_64:
5000 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5001 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005002 case Match_UImm6_0:
5003 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5004 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005005 case Match_UImm6_Lsl2:
5006 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5007 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005008 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005009 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5010 "expected 6-bit signed immediate");
5011 case Match_UImm7_0:
5012 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5013 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005014 case Match_UImm7_N1:
5015 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5016 "expected immediate in range -1 .. 126");
5017 case Match_SImm7_Lsl2:
5018 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5019 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005020 case Match_UImm8_0:
5021 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5022 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005023 case Match_UImm10_0:
5024 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5025 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005026 case Match_SImm10_0:
5027 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5028 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005029 case Match_SImm11_0:
5030 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5031 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005032 case Match_UImm16:
5033 case Match_UImm16_Relaxed:
5034 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5035 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005036 case Match_SImm16:
5037 case Match_SImm16_Relaxed:
5038 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5039 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005040 case Match_SImm19_Lsl2:
5041 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5042 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005043 case Match_UImm20_0:
5044 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5045 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005046 case Match_UImm26_0:
5047 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5048 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005049 case Match_SImm32:
5050 case Match_SImm32_Relaxed:
5051 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5052 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005053 case Match_UImm32_Coerced:
5054 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5055 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005056 case Match_MemSImm9:
5057 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5058 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005059 case Match_MemSImm10:
5060 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5061 "expected memory with 10-bit signed offset");
5062 case Match_MemSImm10Lsl1:
5063 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5064 "expected memory with 11-bit signed offset and multiple of 2");
5065 case Match_MemSImm10Lsl2:
5066 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5067 "expected memory with 12-bit signed offset and multiple of 4");
5068 case Match_MemSImm10Lsl3:
5069 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5070 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005071 case Match_MemSImm11:
5072 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5073 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005074 case Match_MemSImm12:
5075 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5076 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005077 case Match_MemSImm16:
5078 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5079 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00005080 }
Craig Topper589ceee2015-01-03 08:16:34 +00005081
5082 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005083}
5084
Toma Tabacud9d344b2015-04-27 14:05:04 +00005085void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5086 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5087 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5088 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005089}
5090
Toma Tabacu81496c12015-05-20 08:54:45 +00005091void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5092 if (!AssemblerOptions.back()->isMacro())
5093 Warning(Loc, "macro instruction expanded into multiple instructions");
5094}
5095
Daniel Sandersef638fe2014-10-03 15:37:37 +00005096void
5097MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5098 SMRange Range, bool ShowColors) {
5099 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005100 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005101 ShowColors);
5102}
5103
Jack Carter1ac53222013-02-20 23:11:17 +00005104int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005105 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005106
Vladimir Medic4c299852013-11-06 11:27:05 +00005107 CC = StringSwitch<unsigned>(Name)
5108 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005109 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005110 .Case("a0", 4)
5111 .Case("a1", 5)
5112 .Case("a2", 6)
5113 .Case("a3", 7)
5114 .Case("v0", 2)
5115 .Case("v1", 3)
5116 .Case("s0", 16)
5117 .Case("s1", 17)
5118 .Case("s2", 18)
5119 .Case("s3", 19)
5120 .Case("s4", 20)
5121 .Case("s5", 21)
5122 .Case("s6", 22)
5123 .Case("s7", 23)
5124 .Case("k0", 26)
5125 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005126 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005127 .Case("sp", 29)
5128 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005129 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005130 .Case("ra", 31)
5131 .Case("t0", 8)
5132 .Case("t1", 9)
5133 .Case("t2", 10)
5134 .Case("t3", 11)
5135 .Case("t4", 12)
5136 .Case("t5", 13)
5137 .Case("t6", 14)
5138 .Case("t7", 15)
5139 .Case("t8", 24)
5140 .Case("t9", 25)
5141 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005142
Toma Tabacufda445c2014-09-15 15:33:01 +00005143 if (!(isABI_N32() || isABI_N64()))
5144 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005145
Daniel Sandersef638fe2014-10-03 15:37:37 +00005146 if (12 <= CC && CC <= 15) {
5147 // Name is one of t4-t7
5148 AsmToken RegTok = getLexer().peekTok();
5149 SMRange RegRange = RegTok.getLocRange();
5150
5151 StringRef FixedName = StringSwitch<StringRef>(Name)
5152 .Case("t4", "t0")
5153 .Case("t5", "t1")
5154 .Case("t6", "t2")
5155 .Case("t7", "t3")
5156 .Default("");
5157 assert(FixedName != "" && "Register name is not one of t4-t7.");
5158
5159 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5160 "Did you mean $" + FixedName + "?", RegRange);
5161 }
5162
Toma Tabacufda445c2014-09-15 15:33:01 +00005163 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5164 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5165 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5166 if (8 <= CC && CC <= 11)
5167 CC += 4;
5168
5169 if (CC == -1)
5170 CC = StringSwitch<unsigned>(Name)
5171 .Case("a4", 8)
5172 .Case("a5", 9)
5173 .Case("a6", 10)
5174 .Case("a7", 11)
5175 .Case("kt0", 26)
5176 .Case("kt1", 27)
5177 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005178
5179 return CC;
5180}
Jack Carterd0bd6422013-04-18 00:41:53 +00005181
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005182int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5183 int CC;
5184
5185 CC = StringSwitch<unsigned>(Name)
5186 .Case("hwr_cpunum", 0)
5187 .Case("hwr_synci_step", 1)
5188 .Case("hwr_cc", 2)
5189 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005190 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005191 .Default(-1);
5192
5193 return CC;
5194}
5195
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005196int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005197 if (Name[0] == 'f') {
5198 StringRef NumString = Name.substr(1);
5199 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005200 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005201 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005202 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005203 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005204 return IntVal;
5205 }
5206 return -1;
5207}
Jack Cartera63b16a2012-09-07 00:23:42 +00005208
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005209int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005210 if (Name.startswith("fcc")) {
5211 StringRef NumString = Name.substr(3);
5212 unsigned IntVal;
5213 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005214 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005215 if (IntVal > 7) // There are only 8 fcc registers.
5216 return -1;
5217 return IntVal;
5218 }
5219 return -1;
5220}
5221
5222int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005223 if (Name.startswith("ac")) {
5224 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005225 unsigned IntVal;
5226 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005227 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005228 if (IntVal > 3) // There are only 3 acc registers.
5229 return -1;
5230 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005231 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005232 return -1;
5233}
Jack Carterd0bd6422013-04-18 00:41:53 +00005234
Jack Carter5dc8ac92013-09-25 23:50:44 +00005235int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5236 unsigned IntVal;
5237
5238 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5239 return -1;
5240
5241 if (IntVal > 31)
5242 return -1;
5243
5244 return IntVal;
5245}
5246
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005247int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5248 int CC;
5249
5250 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005251 .Case("msair", 0)
5252 .Case("msacsr", 1)
5253 .Case("msaaccess", 2)
5254 .Case("msasave", 3)
5255 .Case("msamodify", 4)
5256 .Case("msarequest", 5)
5257 .Case("msamap", 6)
5258 .Case("msaunmap", 7)
5259 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005260
5261 return CC;
5262}
5263
Simon Dardis3aa8a902017-02-06 12:43:46 +00005264bool MipsAsmParser::canUseATReg() {
5265 return AssemblerOptions.back()->getATRegIndex() != 0;
5266}
5267
Toma Tabacu89a712b2015-04-15 10:48:56 +00005268unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005269 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005270 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005271 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005272 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005273 return 0;
5274 }
5275 unsigned AT = getReg(
5276 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005277 return AT;
5278}
Jack Carter0b744b32012-10-04 02:29:46 +00005279
Jack Carterd0bd6422013-04-18 00:41:53 +00005280unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005281 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005282}
5283
Toma Tabacu13964452014-09-04 13:23:44 +00005284bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005285 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005286 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005287
Jack Carter30a59822012-10-04 04:03:53 +00005288 // Check if the current operand has a custom associated parser, if so, try to
5289 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005290 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5291 if (ResTy == MatchOperand_Success)
5292 return false;
5293 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5294 // there was a match, but an error occurred, in which case, just return that
5295 // the operand parsing failed.
5296 if (ResTy == MatchOperand_ParseFail)
5297 return true;
5298
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005299 DEBUG(dbgs() << ".. Generic Parser\n");
5300
Jack Carterb4dbc172012-09-05 23:34:03 +00005301 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005302 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005303 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005304 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005305
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005306 // Almost all registers have been parsed by custom parsers. There is only
5307 // one exception to this. $zero (and it's alias $0) will reach this point
5308 // for div, divu, and similar instructions because it is not an operand
5309 // to the instruction definition but an explicit register. Special case
5310 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005311 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005312 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005313
Jack Carterd0bd6422013-04-18 00:41:53 +00005314 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005315 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005316 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005317 return true;
5318
Jack Carter873c7242013-01-12 01:03:14 +00005319 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005320 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005321 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005322 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005323 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005324
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005325 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005326 return false;
5327 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005328 default: {
5329 DEBUG(dbgs() << ".. generic integer expression\n");
5330
5331 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005332 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005333 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005334 return true;
5335
Jack Carter873c7242013-01-12 01:03:14 +00005336 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5337
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005338 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005339 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005340 }
Jack Carter0b744b32012-10-04 02:29:46 +00005341 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005342 return true;
5343}
5344
Jack Carterb5cf5902013-04-17 00:18:04 +00005345bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005346 switch (Expr->getKind()) {
5347 case MCExpr::Constant:
5348 return true;
5349 case MCExpr::SymbolRef:
5350 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
5351 case MCExpr::Binary:
5352 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
5353 if (!isEvaluated(BE->getLHS()))
5354 return false;
5355 return isEvaluated(BE->getRHS());
5356 }
5357 case MCExpr::Unary:
5358 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005359 case MCExpr::Target:
5360 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005361 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005362 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005363}
Jack Carterd0bd6422013-04-18 00:41:53 +00005364
Jack Carterb4dbc172012-09-05 23:34:03 +00005365bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5366 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005367 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005368 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005369 if (ResTy == MatchOperand_Success) {
5370 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005371 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005372 StartLoc = Operand.getStartLoc();
5373 EndLoc = Operand.getEndLoc();
5374
5375 // AFAIK, we only support numeric registers and named GPR's in CFI
5376 // directives.
5377 // Don't worry about eating tokens before failing. Using an unrecognised
5378 // register is a parse error.
5379 if (Operand.isGPRAsmReg()) {
5380 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005381 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005382 }
5383
5384 return (RegNo == (unsigned)-1);
5385 }
5386
5387 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005388 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005389}
5390
Jack Carterb5cf5902013-04-17 00:18:04 +00005391bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005392 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005393
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005394 if (isParenExpr)
5395 return getParser().parseParenExprOfDepth(0, Res, S);
5396 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005397}
5398
Alex Bradbury58eba092016-11-01 16:32:05 +00005399OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005400MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005401 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005402 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005403 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005404 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005405 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005406 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005407 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005408 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005409
Jack Carterb5cf5902013-04-17 00:18:04 +00005410 if (getLexer().getKind() == AsmToken::LParen) {
5411 Parser.Lex();
5412 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005413 }
5414
Jack Carterb5cf5902013-04-17 00:18:04 +00005415 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005416 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005417 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005418
Jack Carterd0bd6422013-04-18 00:41:53 +00005419 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005420 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005421 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005422 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005423 SMLoc E =
5424 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005425 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005426 return MatchOperand_Success;
5427 }
5428 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005429 SMLoc E =
5430 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005431
Jack Carterd0bd6422013-04-18 00:41:53 +00005432 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005433 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005434 auto Base = MipsOperand::createGPRReg(
5435 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005436 Operands.push_back(
5437 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005438 return MatchOperand_Success;
5439 }
Simon Dardis858915f2016-10-18 15:17:17 +00005440 MCBinaryExpr::Opcode Opcode;
5441 // GAS and LLVM treat comparison operators different. GAS will generate -1
5442 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5443 // highly unlikely to be found in a memory offset expression, we don't
5444 // handle them.
5445 switch (Tok.getKind()) {
5446 case AsmToken::Plus:
5447 Opcode = MCBinaryExpr::Add;
5448 Parser.Lex();
5449 break;
5450 case AsmToken::Minus:
5451 Opcode = MCBinaryExpr::Sub;
5452 Parser.Lex();
5453 break;
5454 case AsmToken::Star:
5455 Opcode = MCBinaryExpr::Mul;
5456 Parser.Lex();
5457 break;
5458 case AsmToken::Pipe:
5459 Opcode = MCBinaryExpr::Or;
5460 Parser.Lex();
5461 break;
5462 case AsmToken::Amp:
5463 Opcode = MCBinaryExpr::And;
5464 Parser.Lex();
5465 break;
5466 case AsmToken::LessLess:
5467 Opcode = MCBinaryExpr::Shl;
5468 Parser.Lex();
5469 break;
5470 case AsmToken::GreaterGreater:
5471 Opcode = MCBinaryExpr::LShr;
5472 Parser.Lex();
5473 break;
5474 case AsmToken::Caret:
5475 Opcode = MCBinaryExpr::Xor;
5476 Parser.Lex();
5477 break;
5478 case AsmToken::Slash:
5479 Opcode = MCBinaryExpr::Div;
5480 Parser.Lex();
5481 break;
5482 case AsmToken::Percent:
5483 Opcode = MCBinaryExpr::Mod;
5484 Parser.Lex();
5485 break;
5486 default:
5487 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5488 return MatchOperand_ParseFail;
5489 }
5490 const MCExpr * NextExpr;
5491 if (getParser().parseExpression(NextExpr))
5492 return MatchOperand_ParseFail;
5493 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005494 }
5495
Jack Carterd0bd6422013-04-18 00:41:53 +00005496 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005497 }
5498
Toma Tabacu13964452014-09-04 13:23:44 +00005499 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005500 if (Res != MatchOperand_Success)
5501 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005502
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005503 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005504 Error(Parser.getTok().getLoc(), "')' expected");
5505 return MatchOperand_ParseFail;
5506 }
5507
Jack Carter873c7242013-01-12 01:03:14 +00005508 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5509
Jack Carterd0bd6422013-04-18 00:41:53 +00005510 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005511
Craig Topper062a2ba2014-04-25 05:30:21 +00005512 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005513 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005514
Jack Carterd0bd6422013-04-18 00:41:53 +00005515 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005516 std::unique_ptr<MipsOperand> op(
5517 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005518 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005519 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005520 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005521 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005522 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5523 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005524 if (IdVal->evaluateAsAbsolute(Imm))
5525 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005526 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005527 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005528 getContext());
5529 }
5530
David Blaikie960ea3f2014-06-08 16:18:35 +00005531 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005532 return MatchOperand_Success;
5533}
5534
David Blaikie960ea3f2014-06-08 16:18:35 +00005535bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005536 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005537 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005538 if (Sym) {
5539 SMLoc S = Parser.getTok().getLoc();
5540 const MCExpr *Expr;
5541 if (Sym->isVariable())
5542 Expr = Sym->getVariableValue();
5543 else
5544 return false;
5545 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005546 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005547 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005548 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005549 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005550 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005551 if (ResTy == MatchOperand_Success) {
5552 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005553 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005554 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005555 llvm_unreachable("Should never ParseFail");
5556 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005557 }
Jack Carterd76b2372013-03-21 21:44:16 +00005558 }
5559 }
5560 return false;
5561}
Jack Carterd0bd6422013-04-18 00:41:53 +00005562
Alex Bradbury58eba092016-11-01 16:32:05 +00005563OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005564MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005565 StringRef Identifier,
5566 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005567 int Index = matchCPURegisterName(Identifier);
5568 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005569 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005570 Index, Identifier, getContext().getRegisterInfo(), S,
5571 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005572 return MatchOperand_Success;
5573 }
5574
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005575 Index = matchHWRegsRegisterName(Identifier);
5576 if (Index != -1) {
5577 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005578 Index, Identifier, getContext().getRegisterInfo(), S,
5579 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005580 return MatchOperand_Success;
5581 }
5582
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005583 Index = matchFPURegisterName(Identifier);
5584 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005585 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005586 Index, Identifier, getContext().getRegisterInfo(), S,
5587 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005588 return MatchOperand_Success;
5589 }
5590
5591 Index = matchFCCRegisterName(Identifier);
5592 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005593 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005594 Index, Identifier, getContext().getRegisterInfo(), S,
5595 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005596 return MatchOperand_Success;
5597 }
5598
5599 Index = matchACRegisterName(Identifier);
5600 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005601 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005602 Index, Identifier, getContext().getRegisterInfo(), S,
5603 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005604 return MatchOperand_Success;
5605 }
5606
5607 Index = matchMSA128RegisterName(Identifier);
5608 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005609 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005610 Index, Identifier, getContext().getRegisterInfo(), S,
5611 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005612 return MatchOperand_Success;
5613 }
5614
5615 Index = matchMSA128CtrlRegisterName(Identifier);
5616 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005617 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005618 Index, Identifier, getContext().getRegisterInfo(), S,
5619 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005620 return MatchOperand_Success;
5621 }
5622
5623 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005624}
5625
Alex Bradbury58eba092016-11-01 16:32:05 +00005626OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005627MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005628 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005629 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005630
5631 if (Token.is(AsmToken::Identifier)) {
5632 DEBUG(dbgs() << ".. identifier\n");
5633 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005634 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005635 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005636 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005637 } else if (Token.is(AsmToken::Integer)) {
5638 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005639 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005640 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5641 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005642 return MatchOperand_Success;
5643 }
5644
5645 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5646
5647 return MatchOperand_NoMatch;
5648}
5649
Alex Bradbury58eba092016-11-01 16:32:05 +00005650OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005651MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005652 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005653 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005654
5655 auto Token = Parser.getTok();
5656
5657 SMLoc S = Token.getLoc();
5658
5659 if (Token.isNot(AsmToken::Dollar)) {
5660 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5661 if (Token.is(AsmToken::Identifier)) {
5662 if (searchSymbolAlias(Operands))
5663 return MatchOperand_Success;
5664 }
5665 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5666 return MatchOperand_NoMatch;
5667 }
5668 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005669
Toma Tabacu13964452014-09-04 13:23:44 +00005670 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005671 if (ResTy == MatchOperand_Success) {
5672 Parser.Lex(); // $
5673 Parser.Lex(); // identifier
5674 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005675 return ResTy;
5676}
5677
Alex Bradbury58eba092016-11-01 16:32:05 +00005678OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005679MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005680 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005681 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005682
5683 SMLoc S = getLexer().getLoc();
5684
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005685 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005686 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005687 if (ResTy != MatchOperand_NoMatch)
5688 return ResTy;
5689
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005690 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005691 const MCExpr *Expr = nullptr;
5692 if (Parser.parseExpression(Expr)) {
5693 // We have no way of knowing if a symbol was consumed so we must ParseFail
5694 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005695 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005696 Operands.push_back(
5697 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005698 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005699}
5700
Alex Bradbury58eba092016-11-01 16:32:05 +00005701OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005702MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005703 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005704 const MCExpr *IdVal;
5705 // If the first token is '$' we may have register operand.
5706 if (Parser.getTok().is(AsmToken::Dollar))
5707 return MatchOperand_NoMatch;
5708 SMLoc S = Parser.getTok().getLoc();
5709 if (getParser().parseExpression(IdVal))
5710 return MatchOperand_ParseFail;
5711 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005712 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005713 int64_t Val = MCE->getValue();
5714 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5715 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005716 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005717 return MatchOperand_Success;
5718}
5719
Alex Bradbury58eba092016-11-01 16:32:05 +00005720OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005721MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5722 MCAsmParser &Parser = getParser();
5723 SmallVector<unsigned, 10> Regs;
5724 unsigned RegNo;
5725 unsigned PrevReg = Mips::NoRegister;
5726 bool RegRange = false;
5727 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5728
5729 if (Parser.getTok().isNot(AsmToken::Dollar))
5730 return MatchOperand_ParseFail;
5731
5732 SMLoc S = Parser.getTok().getLoc();
5733 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5734 SMLoc E = getLexer().getLoc();
5735 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5736 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5737 if (RegRange) {
5738 // Remove last register operand because registers from register range
5739 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005740 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5741 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005742 Regs.push_back(RegNo);
5743 } else {
5744 unsigned TmpReg = PrevReg + 1;
5745 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005746 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5747 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5748 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005749 Error(E, "invalid register operand");
5750 return MatchOperand_ParseFail;
5751 }
5752
5753 PrevReg = TmpReg;
5754 Regs.push_back(TmpReg++);
5755 }
5756 }
5757
5758 RegRange = false;
5759 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005760 if ((PrevReg == Mips::NoRegister) &&
5761 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5762 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005763 Error(E, "$16 or $31 expected");
5764 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005765 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5766 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5767 !isGP64bit()) ||
5768 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5769 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5770 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005771 Error(E, "invalid register operand");
5772 return MatchOperand_ParseFail;
5773 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005774 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5775 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5776 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005777 Error(E, "consecutive register numbers expected");
5778 return MatchOperand_ParseFail;
5779 }
5780
5781 Regs.push_back(RegNo);
5782 }
5783
5784 if (Parser.getTok().is(AsmToken::Minus))
5785 RegRange = true;
5786
5787 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5788 !Parser.getTok().isNot(AsmToken::Comma)) {
5789 Error(E, "',' or '-' expected");
5790 return MatchOperand_ParseFail;
5791 }
5792
5793 Lex(); // Consume comma or minus
5794 if (Parser.getTok().isNot(AsmToken::Dollar))
5795 break;
5796
5797 PrevReg = RegNo;
5798 }
5799
5800 SMLoc E = Parser.getTok().getLoc();
5801 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5802 parseMemOperand(Operands);
5803 return MatchOperand_Success;
5804}
5805
Alex Bradbury58eba092016-11-01 16:32:05 +00005806OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005807MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5808 MCAsmParser &Parser = getParser();
5809
5810 SMLoc S = Parser.getTok().getLoc();
5811 if (parseAnyRegister(Operands) != MatchOperand_Success)
5812 return MatchOperand_ParseFail;
5813
5814 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005815 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005816
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005817 Operands.pop_back();
5818 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005819 return MatchOperand_Success;
5820}
5821
Alex Bradbury58eba092016-11-01 16:32:05 +00005822OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005823MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5824 MCAsmParser &Parser = getParser();
5825 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5826 SmallVector<unsigned, 10> Regs;
5827
5828 if (Parser.getTok().isNot(AsmToken::Dollar))
5829 return MatchOperand_ParseFail;
5830
5831 SMLoc S = Parser.getTok().getLoc();
5832
5833 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5834 return MatchOperand_ParseFail;
5835
5836 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5837 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5838 Regs.push_back(RegNo);
5839
5840 SMLoc E = Parser.getTok().getLoc();
5841 if (Parser.getTok().isNot(AsmToken::Comma)) {
5842 Error(E, "',' expected");
5843 return MatchOperand_ParseFail;
5844 }
5845
5846 // Remove comma.
5847 Parser.Lex();
5848
5849 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5850 return MatchOperand_ParseFail;
5851
5852 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5853 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5854 Regs.push_back(RegNo);
5855
5856 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5857
5858 return MatchOperand_Success;
5859}
5860
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005861/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5862/// either this.
5863/// ::= '(', register, ')'
5864/// handle it before we iterate so we don't get tripped up by the lack of
5865/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005866bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005867 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005868 if (getLexer().is(AsmToken::LParen)) {
5869 Operands.push_back(
5870 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5871 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005872 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005873 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005874 return Error(Loc, "unexpected token in argument list");
5875 }
5876 if (Parser.getTok().isNot(AsmToken::RParen)) {
5877 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005878 return Error(Loc, "unexpected token, expected ')'");
5879 }
5880 Operands.push_back(
5881 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5882 Parser.Lex();
5883 }
5884 return false;
5885}
5886
5887/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5888/// either one of these.
5889/// ::= '[', register, ']'
5890/// ::= '[', integer, ']'
5891/// handle it before we iterate so we don't get tripped up by the lack of
5892/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005893bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005894 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005895 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005896 if (getLexer().is(AsmToken::LBrac)) {
5897 Operands.push_back(
5898 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5899 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005900 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005901 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005902 return Error(Loc, "unexpected token in argument list");
5903 }
5904 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5905 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005906 return Error(Loc, "unexpected token, expected ']'");
5907 }
5908 Operands.push_back(
5909 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5910 Parser.Lex();
5911 }
5912 return false;
5913}
5914
David Blaikie960ea3f2014-06-08 16:18:35 +00005915bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5916 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005917 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005918 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005919
5920 // We have reached first instruction, module directive are now forbidden.
5921 getTargetStreamer().forbidModuleDirective();
5922
Vladimir Medic74593e62013-07-17 15:00:42 +00005923 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005924 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005925 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005926 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005927 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005928 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005929
5930 // Read the remaining operands.
5931 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5932 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005933 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005934 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005935 return Error(Loc, "unexpected token in argument list");
5936 }
Toma Tabacu13964452014-09-04 13:23:44 +00005937 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005938 return true;
5939 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005940
Jack Carterd0bd6422013-04-18 00:41:53 +00005941 while (getLexer().is(AsmToken::Comma)) {
5942 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005943 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005944 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005945 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005946 return Error(Loc, "unexpected token in argument list");
5947 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005948 // Parse bracket and parenthesis suffixes before we iterate
5949 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005950 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005951 return true;
5952 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005953 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005954 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005955 }
5956 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5958 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005959 return Error(Loc, "unexpected token in argument list");
5960 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005961 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005962 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005963}
5964
Nirav Dave996fc132016-05-05 14:15:46 +00005965// FIXME: Given that these have the same name, these should both be
5966// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005967bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005968 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005969 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005970}
5971
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005972bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005973 return Error(Loc, ErrorMsg);
5974}
5975
Jack Carter0b744b32012-10-04 02:29:46 +00005976bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005977 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005978 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005979
5980 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005981 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005982
5983 Parser.Lex(); // Eat "noat".
5984
Jack Carterd0bd6422013-04-18 00:41:53 +00005985 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005986 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005987 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005988 return false;
5989 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005990
5991 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005992 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005993 return false;
5994}
Jack Carterd0bd6422013-04-18 00:41:53 +00005995
Jack Carter0b744b32012-10-04 02:29:46 +00005996bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005997 // Line can be: ".set at", which sets $at to $1
5998 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005999 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006000 Parser.Lex(); // Eat "at".
6001
Jack Carter0b744b32012-10-04 02:29:46 +00006002 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006003 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006004 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006005
6006 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006007 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006008 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006009 }
6010
6011 if (getLexer().isNot(AsmToken::Equal)) {
6012 reportParseError("unexpected token, expected equals sign");
6013 return false;
6014 }
6015 Parser.Lex(); // Eat "=".
6016
6017 if (getLexer().isNot(AsmToken::Dollar)) {
6018 if (getLexer().is(AsmToken::EndOfStatement)) {
6019 reportParseError("no register specified");
6020 return false;
6021 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006022 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006023 return false;
6024 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006025 }
6026 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006027
Toma Tabacu16a74492015-02-13 10:30:57 +00006028 // Find out what "reg" is.
6029 unsigned AtRegNo;
6030 const AsmToken &Reg = Parser.getTok();
6031 if (Reg.is(AsmToken::Identifier)) {
6032 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6033 } else if (Reg.is(AsmToken::Integer)) {
6034 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006035 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006036 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006037 return false;
6038 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006039
6040 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006041 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006042 reportParseError("invalid register");
6043 return false;
6044 }
6045 Parser.Lex(); // Eat "reg".
6046
6047 // If this is not the end of the statement, report an error.
6048 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6049 reportParseError("unexpected token, expected end of statement");
6050 return false;
6051 }
6052
6053 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6054
6055 Parser.Lex(); // Consume the EndOfStatement.
6056 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006057}
6058
6059bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006060 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006061 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006062 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006063 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006064 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006065 return false;
6066 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006067 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006068 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006069 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006070 return false;
6071}
6072
6073bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006074 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006075 Parser.Lex();
6076 // If this is not the end of the statement, report an error.
6077 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006078 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006079 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006080 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006081 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006082 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006083 Parser.Lex(); // Consume the EndOfStatement.
6084 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006085}
6086
6087bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006088 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006089 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006090 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006091 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006092 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006093 return false;
6094 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006095 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006096 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006097 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006098 return false;
6099}
6100
6101bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006102 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006103 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006104 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006105 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006106 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006107 return false;
6108 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006109 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006110 reportParseError("`noreorder' must be set before `nomacro'");
6111 return false;
6112 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006113 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006114 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006115 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006116 return false;
6117}
Jack Carterd76b2372013-03-21 21:44:16 +00006118
Daniel Sanders44934432014-08-07 12:03:36 +00006119bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006120 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006121 Parser.Lex();
6122
6123 // If this is not the end of the statement, report an error.
6124 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006125 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006126
6127 setFeatureBits(Mips::FeatureMSA, "msa");
6128 getTargetStreamer().emitDirectiveSetMsa();
6129 return false;
6130}
6131
6132bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006133 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006134 Parser.Lex();
6135
6136 // If this is not the end of the statement, report an error.
6137 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006138 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006139
6140 clearFeatureBits(Mips::FeatureMSA, "msa");
6141 getTargetStreamer().emitDirectiveSetNoMsa();
6142 return false;
6143}
6144
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006145bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006146 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006147 Parser.Lex(); // Eat "nodsp".
6148
6149 // If this is not the end of the statement, report an error.
6150 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6151 reportParseError("unexpected token, expected end of statement");
6152 return false;
6153 }
6154
6155 clearFeatureBits(Mips::FeatureDSP, "dsp");
6156 getTargetStreamer().emitDirectiveSetNoDsp();
6157 return false;
6158}
6159
Toma Tabacucc2502d2014-11-04 17:18:07 +00006160bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006161 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006162 Parser.Lex(); // Eat "mips16".
6163
Jack Carter39536722014-01-22 23:08:42 +00006164 // If this is not the end of the statement, report an error.
6165 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006166 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006167 return false;
6168 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006169
6170 setFeatureBits(Mips::FeatureMips16, "mips16");
6171 getTargetStreamer().emitDirectiveSetMips16();
6172 Parser.Lex(); // Consume the EndOfStatement.
6173 return false;
6174}
6175
6176bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006177 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006178 Parser.Lex(); // Eat "nomips16".
6179
6180 // If this is not the end of the statement, report an error.
6181 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6182 reportParseError("unexpected token, expected end of statement");
6183 return false;
6184 }
6185
6186 clearFeatureBits(Mips::FeatureMips16, "mips16");
6187 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006188 Parser.Lex(); // Consume the EndOfStatement.
6189 return false;
6190}
6191
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006192bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006193 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006194 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006195 // Line can be: .set fp=32
6196 // .set fp=xx
6197 // .set fp=64
6198 Parser.Lex(); // Eat fp token
6199 AsmToken Tok = Parser.getTok();
6200 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006201 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006202 return false;
6203 }
6204 Parser.Lex(); // Eat '=' token.
6205 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006206
6207 if (!parseFpABIValue(FpAbiVal, ".set"))
6208 return false;
6209
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006210 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006211 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006212 return false;
6213 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006214 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006215 Parser.Lex(); // Consume the EndOfStatement.
6216 return false;
6217}
6218
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006219bool MipsAsmParser::parseSetOddSPRegDirective() {
6220 MCAsmParser &Parser = getParser();
6221
6222 Parser.Lex(); // Eat "oddspreg".
6223 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6224 reportParseError("unexpected token, expected end of statement");
6225 return false;
6226 }
6227
6228 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6229 getTargetStreamer().emitDirectiveSetOddSPReg();
6230 return false;
6231}
6232
6233bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6234 MCAsmParser &Parser = getParser();
6235
6236 Parser.Lex(); // Eat "nooddspreg".
6237 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6238 reportParseError("unexpected token, expected end of statement");
6239 return false;
6240 }
6241
6242 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6243 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6244 return false;
6245}
6246
Toma Tabacu9db22db2014-09-09 10:15:38 +00006247bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006248 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006249 SMLoc Loc = getLexer().getLoc();
6250
6251 Parser.Lex();
6252 if (getLexer().isNot(AsmToken::EndOfStatement))
6253 return reportParseError("unexpected token, expected end of statement");
6254
6255 // Always keep an element on the options "stack" to prevent the user
6256 // from changing the initial options. This is how we remember them.
6257 if (AssemblerOptions.size() == 2)
6258 return reportParseError(Loc, ".set pop with no .set push");
6259
Akira Hatanakab11ef082015-11-14 06:35:56 +00006260 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006261 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006262 setAvailableFeatures(
6263 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6264 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006265
6266 getTargetStreamer().emitDirectiveSetPop();
6267 return false;
6268}
6269
6270bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006271 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006272 Parser.Lex();
6273 if (getLexer().isNot(AsmToken::EndOfStatement))
6274 return reportParseError("unexpected token, expected end of statement");
6275
6276 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006277 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006278 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006279
6280 getTargetStreamer().emitDirectiveSetPush();
6281 return false;
6282}
6283
Toma Tabacu29696502015-06-02 09:48:04 +00006284bool MipsAsmParser::parseSetSoftFloatDirective() {
6285 MCAsmParser &Parser = getParser();
6286 Parser.Lex();
6287 if (getLexer().isNot(AsmToken::EndOfStatement))
6288 return reportParseError("unexpected token, expected end of statement");
6289
6290 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6291 getTargetStreamer().emitDirectiveSetSoftFloat();
6292 return false;
6293}
6294
6295bool MipsAsmParser::parseSetHardFloatDirective() {
6296 MCAsmParser &Parser = getParser();
6297 Parser.Lex();
6298 if (getLexer().isNot(AsmToken::EndOfStatement))
6299 return reportParseError("unexpected token, expected end of statement");
6300
6301 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6302 getTargetStreamer().emitDirectiveSetHardFloat();
6303 return false;
6304}
6305
Jack Carterd76b2372013-03-21 21:44:16 +00006306bool MipsAsmParser::parseSetAssignment() {
6307 StringRef Name;
6308 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006309 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006310
6311 if (Parser.parseIdentifier(Name))
6312 reportParseError("expected identifier after .set");
6313
6314 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006315 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006316 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006317
Jack Carter3b2c96e2014-01-22 23:31:38 +00006318 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006319 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006320
Jim Grosbach6f482002015-05-18 18:43:14 +00006321 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006322 Sym->setVariableValue(Value);
6323
6324 return false;
6325}
Jack Carterd0bd6422013-04-18 00:41:53 +00006326
Toma Tabacu26647792014-09-09 12:52:14 +00006327bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006328 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006329 Parser.Lex();
6330 if (getLexer().isNot(AsmToken::EndOfStatement))
6331 return reportParseError("unexpected token, expected end of statement");
6332
6333 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006334 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006335 setAvailableFeatures(
6336 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6337 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006338 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6339
6340 getTargetStreamer().emitDirectiveSetMips0();
6341 return false;
6342}
6343
Toma Tabacu85618b32014-08-19 14:22:52 +00006344bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006345 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006346 Parser.Lex();
6347 if (getLexer().isNot(AsmToken::Equal))
6348 return reportParseError("unexpected token, expected equals sign");
6349
6350 Parser.Lex();
6351 StringRef Arch;
6352 if (Parser.parseIdentifier(Arch))
6353 return reportParseError("expected arch identifier");
6354
6355 StringRef ArchFeatureName =
6356 StringSwitch<StringRef>(Arch)
6357 .Case("mips1", "mips1")
6358 .Case("mips2", "mips2")
6359 .Case("mips3", "mips3")
6360 .Case("mips4", "mips4")
6361 .Case("mips5", "mips5")
6362 .Case("mips32", "mips32")
6363 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006364 .Case("mips32r3", "mips32r3")
6365 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006366 .Case("mips32r6", "mips32r6")
6367 .Case("mips64", "mips64")
6368 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006369 .Case("mips64r3", "mips64r3")
6370 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006371 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006372 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006373 .Case("r4000", "mips3") // This is an implementation of Mips3.
6374 .Default("");
6375
6376 if (ArchFeatureName.empty())
6377 return reportParseError("unsupported architecture");
6378
6379 selectArch(ArchFeatureName);
6380 getTargetStreamer().emitDirectiveSetArch(Arch);
6381 return false;
6382}
6383
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006384bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006385 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006386 Parser.Lex();
6387 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006388 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006389
Matheus Almeida2852af82014-04-22 10:15:54 +00006390 switch (Feature) {
6391 default:
6392 llvm_unreachable("Unimplemented feature");
6393 case Mips::FeatureDSP:
6394 setFeatureBits(Mips::FeatureDSP, "dsp");
6395 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006396 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006397 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006398 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006399 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006400 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006401 case Mips::FeatureMips1:
6402 selectArch("mips1");
6403 getTargetStreamer().emitDirectiveSetMips1();
6404 break;
6405 case Mips::FeatureMips2:
6406 selectArch("mips2");
6407 getTargetStreamer().emitDirectiveSetMips2();
6408 break;
6409 case Mips::FeatureMips3:
6410 selectArch("mips3");
6411 getTargetStreamer().emitDirectiveSetMips3();
6412 break;
6413 case Mips::FeatureMips4:
6414 selectArch("mips4");
6415 getTargetStreamer().emitDirectiveSetMips4();
6416 break;
6417 case Mips::FeatureMips5:
6418 selectArch("mips5");
6419 getTargetStreamer().emitDirectiveSetMips5();
6420 break;
6421 case Mips::FeatureMips32:
6422 selectArch("mips32");
6423 getTargetStreamer().emitDirectiveSetMips32();
6424 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006425 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006426 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006427 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006428 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006429 case Mips::FeatureMips32r3:
6430 selectArch("mips32r3");
6431 getTargetStreamer().emitDirectiveSetMips32R3();
6432 break;
6433 case Mips::FeatureMips32r5:
6434 selectArch("mips32r5");
6435 getTargetStreamer().emitDirectiveSetMips32R5();
6436 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006437 case Mips::FeatureMips32r6:
6438 selectArch("mips32r6");
6439 getTargetStreamer().emitDirectiveSetMips32R6();
6440 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006441 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006442 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006443 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006444 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006445 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006446 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006447 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006448 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006449 case Mips::FeatureMips64r3:
6450 selectArch("mips64r3");
6451 getTargetStreamer().emitDirectiveSetMips64R3();
6452 break;
6453 case Mips::FeatureMips64r5:
6454 selectArch("mips64r5");
6455 getTargetStreamer().emitDirectiveSetMips64R5();
6456 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006457 case Mips::FeatureMips64r6:
6458 selectArch("mips64r6");
6459 getTargetStreamer().emitDirectiveSetMips64R6();
6460 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006461 }
6462 return false;
6463}
6464
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006465bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006466 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006467 if (getLexer().isNot(AsmToken::Comma)) {
6468 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006469 return Error(Loc, ErrorStr);
6470 }
6471
Matheus Almeida2852af82014-04-22 10:15:54 +00006472 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006473 return true;
6474}
6475
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006476// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6477// In this class, it is only used for .cprestore.
6478// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6479// MipsTargetELFStreamer and MipsAsmParser.
6480bool MipsAsmParser::isPicAndNotNxxAbi() {
6481 return inPicMode() && !(isABI_N32() || isABI_N64());
6482}
6483
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006484bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006485 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006486 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006487
Toma Tabacudde4c462014-11-06 10:02:45 +00006488 if (inMips16Mode()) {
6489 reportParseError(".cpload is not supported in Mips16 mode");
6490 return false;
6491 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006492
David Blaikie960ea3f2014-06-08 16:18:35 +00006493 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006494 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006495 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6496 reportParseError("expected register containing function address");
6497 return false;
6498 }
6499
David Blaikie960ea3f2014-06-08 16:18:35 +00006500 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6501 if (!RegOpnd.isGPRAsmReg()) {
6502 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006503 return false;
6504 }
6505
Toma Tabacudde4c462014-11-06 10:02:45 +00006506 // If this is not the end of the statement, report an error.
6507 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6508 reportParseError("unexpected token, expected end of statement");
6509 return false;
6510 }
6511
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006512 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006513 return false;
6514}
6515
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006516bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6517 MCAsmParser &Parser = getParser();
6518
6519 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6520 // is used in non-PIC mode.
6521
6522 if (inMips16Mode()) {
6523 reportParseError(".cprestore is not supported in Mips16 mode");
6524 return false;
6525 }
6526
6527 // Get the stack offset value.
6528 const MCExpr *StackOffset;
6529 int64_t StackOffsetVal;
6530 if (Parser.parseExpression(StackOffset)) {
6531 reportParseError("expected stack offset value");
6532 return false;
6533 }
6534
6535 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6536 reportParseError("stack offset is not an absolute expression");
6537 return false;
6538 }
6539
6540 if (StackOffsetVal < 0) {
6541 Warning(Loc, ".cprestore with negative stack offset has no effect");
6542 IsCpRestoreSet = false;
6543 } else {
6544 IsCpRestoreSet = true;
6545 CpRestoreOffset = StackOffsetVal;
6546 }
6547
6548 // If this is not the end of the statement, report an error.
6549 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6550 reportParseError("unexpected token, expected end of statement");
6551 return false;
6552 }
6553
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006554 if (!getTargetStreamer().emitDirectiveCpRestore(
6555 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006556 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006557 Parser.Lex(); // Consume the EndOfStatement.
6558 return false;
6559}
6560
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006561bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006562 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006563 unsigned FuncReg;
6564 unsigned Save;
6565 bool SaveIsReg = true;
6566
Matheus Almeida7e815762014-06-18 13:08:59 +00006567 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006568 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006569 if (ResTy == MatchOperand_NoMatch) {
6570 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006571 return false;
6572 }
6573
6574 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6575 if (!FuncRegOpnd.isGPRAsmReg()) {
6576 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006577 return false;
6578 }
6579
6580 FuncReg = FuncRegOpnd.getGPR32Reg();
6581 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006582
Toma Tabacu65f10572014-09-16 15:00:52 +00006583 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006584 return true;
6585
Toma Tabacu13964452014-09-04 13:23:44 +00006586 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006587 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006588 const MCExpr *OffsetExpr;
6589 int64_t OffsetVal;
6590 SMLoc ExprLoc = getLexer().getLoc();
6591
6592 if (Parser.parseExpression(OffsetExpr) ||
6593 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6594 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006595 return false;
6596 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006597
6598 Save = OffsetVal;
6599 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006600 } else {
6601 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6602 if (!SaveOpnd.isGPRAsmReg()) {
6603 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006604 return false;
6605 }
6606 Save = SaveOpnd.getGPR32Reg();
6607 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006608
Toma Tabacu65f10572014-09-16 15:00:52 +00006609 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006610 return true;
6611
Toma Tabacu8874eac2015-02-18 13:46:53 +00006612 const MCExpr *Expr;
6613 if (Parser.parseExpression(Expr)) {
6614 reportParseError("expected expression");
6615 return false;
6616 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006617
Toma Tabacu8874eac2015-02-18 13:46:53 +00006618 if (Expr->getKind() != MCExpr::SymbolRef) {
6619 reportParseError("expected symbol");
6620 return false;
6621 }
6622 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6623
Daniel Sandersf173dda2015-09-22 10:50:09 +00006624 CpSaveLocation = Save;
6625 CpSaveLocationIsRegister = SaveIsReg;
6626
Toma Tabacu8874eac2015-02-18 13:46:53 +00006627 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6628 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006629 return false;
6630}
6631
Daniel Sandersf173dda2015-09-22 10:50:09 +00006632bool MipsAsmParser::parseDirectiveCPReturn() {
6633 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6634 CpSaveLocationIsRegister);
6635 return false;
6636}
6637
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006638bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006639 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006640 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6641 const AsmToken &Tok = Parser.getTok();
6642
6643 if (Tok.getString() == "2008") {
6644 Parser.Lex();
6645 getTargetStreamer().emitDirectiveNaN2008();
6646 return false;
6647 } else if (Tok.getString() == "legacy") {
6648 Parser.Lex();
6649 getTargetStreamer().emitDirectiveNaNLegacy();
6650 return false;
6651 }
6652 }
6653 // If we don't recognize the option passed to the .nan
6654 // directive (e.g. no option or unknown option), emit an error.
6655 reportParseError("invalid option in .nan directive");
6656 return false;
6657}
6658
Jack Carter0b744b32012-10-04 02:29:46 +00006659bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006660 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006661 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006662 const AsmToken &Tok = Parser.getTok();
6663
6664 if (Tok.getString() == "noat") {
6665 return parseSetNoAtDirective();
6666 } else if (Tok.getString() == "at") {
6667 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006668 } else if (Tok.getString() == "arch") {
6669 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006670 } else if (Tok.getString() == "bopt") {
6671 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6672 getParser().Lex();
6673 return false;
6674 } else if (Tok.getString() == "nobopt") {
6675 // We're already running in nobopt mode, so nothing to do.
6676 getParser().Lex();
6677 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006678 } else if (Tok.getString() == "fp") {
6679 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006680 } else if (Tok.getString() == "oddspreg") {
6681 return parseSetOddSPRegDirective();
6682 } else if (Tok.getString() == "nooddspreg") {
6683 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006684 } else if (Tok.getString() == "pop") {
6685 return parseSetPopDirective();
6686 } else if (Tok.getString() == "push") {
6687 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006688 } else if (Tok.getString() == "reorder") {
6689 return parseSetReorderDirective();
6690 } else if (Tok.getString() == "noreorder") {
6691 return parseSetNoReorderDirective();
6692 } else if (Tok.getString() == "macro") {
6693 return parseSetMacroDirective();
6694 } else if (Tok.getString() == "nomacro") {
6695 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006696 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006697 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006698 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006699 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006700 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006701 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006702 getTargetStreamer().emitDirectiveSetNoMicroMips();
6703 Parser.eatToEndOfStatement();
6704 return false;
6705 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006706 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006707 } else if (Tok.getString() == "mips0") {
6708 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006709 } else if (Tok.getString() == "mips1") {
6710 return parseSetFeature(Mips::FeatureMips1);
6711 } else if (Tok.getString() == "mips2") {
6712 return parseSetFeature(Mips::FeatureMips2);
6713 } else if (Tok.getString() == "mips3") {
6714 return parseSetFeature(Mips::FeatureMips3);
6715 } else if (Tok.getString() == "mips4") {
6716 return parseSetFeature(Mips::FeatureMips4);
6717 } else if (Tok.getString() == "mips5") {
6718 return parseSetFeature(Mips::FeatureMips5);
6719 } else if (Tok.getString() == "mips32") {
6720 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006721 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006722 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006723 } else if (Tok.getString() == "mips32r3") {
6724 return parseSetFeature(Mips::FeatureMips32r3);
6725 } else if (Tok.getString() == "mips32r5") {
6726 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006727 } else if (Tok.getString() == "mips32r6") {
6728 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006729 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006730 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006731 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006732 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006733 } else if (Tok.getString() == "mips64r3") {
6734 return parseSetFeature(Mips::FeatureMips64r3);
6735 } else if (Tok.getString() == "mips64r5") {
6736 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006737 } else if (Tok.getString() == "mips64r6") {
6738 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006739 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006740 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006741 } else if (Tok.getString() == "nodsp") {
6742 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006743 } else if (Tok.getString() == "msa") {
6744 return parseSetMsaDirective();
6745 } else if (Tok.getString() == "nomsa") {
6746 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006747 } else if (Tok.getString() == "softfloat") {
6748 return parseSetSoftFloatDirective();
6749 } else if (Tok.getString() == "hardfloat") {
6750 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006751 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006752 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006753 parseSetAssignment();
6754 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006755 }
Jack Carter07c818d2013-01-25 01:31:34 +00006756
Jack Carter0b744b32012-10-04 02:29:46 +00006757 return true;
6758}
6759
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006760/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006761/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006762bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006763 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006764 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006765 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006766 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006767 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006768 return true;
6769
6770 getParser().getStreamer().EmitValue(Value, Size);
6771
6772 if (getLexer().is(AsmToken::EndOfStatement))
6773 break;
6774
Jack Carter07c818d2013-01-25 01:31:34 +00006775 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006776 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006777 Parser.Lex();
6778 }
6779 }
6780
6781 Parser.Lex();
6782 return false;
6783}
6784
Vladimir Medic4c299852013-11-06 11:27:05 +00006785/// parseDirectiveGpWord
6786/// ::= .gpword local_sym
6787bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006788 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006789 const MCExpr *Value;
6790 // EmitGPRel32Value requires an expression, so we are using base class
6791 // method to evaluate the expression.
6792 if (getParser().parseExpression(Value))
6793 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006794 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006795
Vladimir Medice10c1122013-11-13 13:18:04 +00006796 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006797 return Error(getLexer().getLoc(),
6798 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006799 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006800 return false;
6801}
6802
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006803/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006804/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006805bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006806 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006807 const MCExpr *Value;
6808 // EmitGPRel64Value requires an expression, so we are using base class
6809 // method to evaluate the expression.
6810 if (getParser().parseExpression(Value))
6811 return true;
6812 getParser().getStreamer().EmitGPRel64Value(Value);
6813
6814 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006815 return Error(getLexer().getLoc(),
6816 "unexpected token, expected end of statement");
6817 Parser.Lex(); // Eat EndOfStatement token.
6818 return false;
6819}
6820
6821/// parseDirectiveDtpRelWord
6822/// ::= .dtprelword tls_sym
6823bool MipsAsmParser::parseDirectiveDtpRelWord() {
6824 MCAsmParser &Parser = getParser();
6825 const MCExpr *Value;
6826 // EmitDTPRel32Value requires an expression, so we are using base class
6827 // method to evaluate the expression.
6828 if (getParser().parseExpression(Value))
6829 return true;
6830 getParser().getStreamer().EmitDTPRel32Value(Value);
6831
6832 if (getLexer().isNot(AsmToken::EndOfStatement))
6833 return Error(getLexer().getLoc(),
6834 "unexpected token, expected end of statement");
6835 Parser.Lex(); // Eat EndOfStatement token.
6836 return false;
6837}
6838
6839/// parseDirectiveDtpRelDWord
6840/// ::= .dtpreldword tls_sym
6841bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6842 MCAsmParser &Parser = getParser();
6843 const MCExpr *Value;
6844 // EmitDTPRel64Value requires an expression, so we are using base class
6845 // method to evaluate the expression.
6846 if (getParser().parseExpression(Value))
6847 return true;
6848 getParser().getStreamer().EmitDTPRel64Value(Value);
6849
6850 if (getLexer().isNot(AsmToken::EndOfStatement))
6851 return Error(getLexer().getLoc(),
6852 "unexpected token, expected end of statement");
6853 Parser.Lex(); // Eat EndOfStatement token.
6854 return false;
6855}
6856
6857/// parseDirectiveTpRelWord
6858/// ::= .tprelword tls_sym
6859bool MipsAsmParser::parseDirectiveTpRelWord() {
6860 MCAsmParser &Parser = getParser();
6861 const MCExpr *Value;
6862 // EmitTPRel32Value requires an expression, so we are using base class
6863 // method to evaluate the expression.
6864 if (getParser().parseExpression(Value))
6865 return true;
6866 getParser().getStreamer().EmitTPRel32Value(Value);
6867
6868 if (getLexer().isNot(AsmToken::EndOfStatement))
6869 return Error(getLexer().getLoc(),
6870 "unexpected token, expected end of statement");
6871 Parser.Lex(); // Eat EndOfStatement token.
6872 return false;
6873}
6874
6875/// parseDirectiveTpRelDWord
6876/// ::= .tpreldword tls_sym
6877bool MipsAsmParser::parseDirectiveTpRelDWord() {
6878 MCAsmParser &Parser = getParser();
6879 const MCExpr *Value;
6880 // EmitTPRel64Value requires an expression, so we are using base class
6881 // method to evaluate the expression.
6882 if (getParser().parseExpression(Value))
6883 return true;
6884 getParser().getStreamer().EmitTPRel64Value(Value);
6885
6886 if (getLexer().isNot(AsmToken::EndOfStatement))
6887 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006888 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006889 Parser.Lex(); // Eat EndOfStatement token.
6890 return false;
6891}
6892
Jack Carter0cd3c192014-01-06 23:27:31 +00006893bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006894 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006895 // Get the option token.
6896 AsmToken Tok = Parser.getTok();
6897 // At the moment only identifiers are supported.
6898 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006899 return Error(Parser.getTok().getLoc(),
6900 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006901 }
6902
6903 StringRef Option = Tok.getIdentifier();
6904
6905 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006906 // MipsAsmParser needs to know if the current PIC mode changes.
6907 IsPicEnabled = false;
6908
Jack Carter0cd3c192014-01-06 23:27:31 +00006909 getTargetStreamer().emitDirectiveOptionPic0();
6910 Parser.Lex();
6911 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006912 return Error(Parser.getTok().getLoc(),
6913 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006914 }
6915 return false;
6916 }
6917
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006918 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006919 // MipsAsmParser needs to know if the current PIC mode changes.
6920 IsPicEnabled = true;
6921
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006922 getTargetStreamer().emitDirectiveOptionPic2();
6923 Parser.Lex();
6924 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006925 return Error(Parser.getTok().getLoc(),
6926 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006927 }
6928 return false;
6929 }
6930
Jack Carter0cd3c192014-01-06 23:27:31 +00006931 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006932 Warning(Parser.getTok().getLoc(),
6933 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006934 Parser.eatToEndOfStatement();
6935 return false;
6936}
6937
Toma Tabacu9ca50962015-04-16 09:53:47 +00006938/// parseInsnDirective
6939/// ::= .insn
6940bool MipsAsmParser::parseInsnDirective() {
6941 // If this is not the end of the statement, report an error.
6942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6943 reportParseError("unexpected token, expected end of statement");
6944 return false;
6945 }
6946
6947 // The actual label marking happens in
6948 // MipsELFStreamer::createPendingLabelRelocs().
6949 getTargetStreamer().emitDirectiveInsn();
6950
6951 getParser().Lex(); // Eat EndOfStatement token.
6952 return false;
6953}
6954
Simon Atanasyanbe186202016-02-11 06:45:54 +00006955/// parseSSectionDirective
6956/// ::= .sbss
6957/// ::= .sdata
6958bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
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, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6967 getParser().getStreamer().SwitchSection(ELFSection);
6968
6969 getParser().Lex(); // Eat EndOfStatement token.
6970 return false;
6971}
6972
Daniel Sanders7e527422014-07-10 13:38:23 +00006973/// parseDirectiveModule
6974/// ::= .module oddspreg
6975/// ::= .module nooddspreg
6976/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006977/// ::= .module softfloat
6978/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006979bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006980 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006981 MCAsmLexer &Lexer = getLexer();
6982 SMLoc L = Lexer.getLoc();
6983
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006984 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006985 // TODO : get a better message.
6986 reportParseError(".module directive must appear before any code");
6987 return false;
6988 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006989
Toma Tabacuc405c822015-01-23 10:40:19 +00006990 StringRef Option;
6991 if (Parser.parseIdentifier(Option)) {
6992 reportParseError("expected .module option identifier");
6993 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006994 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006995
Toma Tabacuc405c822015-01-23 10:40:19 +00006996 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006997 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006998
Toma Tabacu3c499582015-06-25 10:56:57 +00006999 // Synchronize the abiflags information with the FeatureBits information we
7000 // changed above.
7001 getTargetStreamer().updateABIInfo(*this);
7002
7003 // If printing assembly, use the recently updated abiflags information.
7004 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7005 // emitted at the end).
7006 getTargetStreamer().emitDirectiveModuleOddSPReg();
7007
Toma Tabacuc405c822015-01-23 10:40:19 +00007008 // If this is not the end of the statement, report an error.
7009 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7010 reportParseError("unexpected token, expected end of statement");
7011 return false;
7012 }
7013
7014 return false; // parseDirectiveModule has finished successfully.
7015 } else if (Option == "nooddspreg") {
7016 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007017 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007018 }
7019
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007020 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007021
Toma Tabacu3c499582015-06-25 10:56:57 +00007022 // Synchronize the abiflags information with the FeatureBits information we
7023 // changed above.
7024 getTargetStreamer().updateABIInfo(*this);
7025
7026 // If printing assembly, use the recently updated abiflags information.
7027 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7028 // emitted at the end).
7029 getTargetStreamer().emitDirectiveModuleOddSPReg();
7030
Toma Tabacuc405c822015-01-23 10:40:19 +00007031 // If this is not the end of the statement, report an error.
7032 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7033 reportParseError("unexpected token, expected end of statement");
7034 return false;
7035 }
7036
7037 return false; // parseDirectiveModule has finished successfully.
7038 } else if (Option == "fp") {
7039 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007040 } else if (Option == "softfloat") {
7041 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7042
7043 // Synchronize the ABI Flags information with the FeatureBits information we
7044 // updated above.
7045 getTargetStreamer().updateABIInfo(*this);
7046
7047 // If printing assembly, use the recently updated ABI Flags information.
7048 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7049 // emitted later).
7050 getTargetStreamer().emitDirectiveModuleSoftFloat();
7051
7052 // If this is not the end of the statement, report an error.
7053 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7054 reportParseError("unexpected token, expected end of statement");
7055 return false;
7056 }
7057
7058 return false; // parseDirectiveModule has finished successfully.
7059 } else if (Option == "hardfloat") {
7060 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7061
7062 // Synchronize the ABI Flags information with the FeatureBits information we
7063 // updated above.
7064 getTargetStreamer().updateABIInfo(*this);
7065
7066 // If printing assembly, use the recently updated ABI Flags information.
7067 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7068 // emitted later).
7069 getTargetStreamer().emitDirectiveModuleHardFloat();
7070
7071 // If this is not the end of the statement, report an error.
7072 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7073 reportParseError("unexpected token, expected end of statement");
7074 return false;
7075 }
7076
7077 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007078 } else {
7079 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7080 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007081}
7082
7083/// parseDirectiveModuleFP
7084/// ::= =32
7085/// ::= =xx
7086/// ::= =64
7087bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007088 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007089 MCAsmLexer &Lexer = getLexer();
7090
7091 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007092 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007093 return false;
7094 }
7095 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007096
Daniel Sanders7e527422014-07-10 13:38:23 +00007097 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007098 if (!parseFpABIValue(FpABI, ".module"))
7099 return false;
7100
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007101 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007102 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007103 return false;
7104 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007105
Toma Tabacua64e5402015-06-25 12:44:38 +00007106 // Synchronize the abiflags information with the FeatureBits information we
7107 // changed above.
7108 getTargetStreamer().updateABIInfo(*this);
7109
7110 // If printing assembly, use the recently updated abiflags information.
7111 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7112 // emitted at the end).
7113 getTargetStreamer().emitDirectiveModuleFP();
7114
Daniel Sanders7e527422014-07-10 13:38:23 +00007115 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007116 return false;
7117}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007118
Daniel Sanders7e527422014-07-10 13:38:23 +00007119bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007120 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007121 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007122 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007123 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007124
7125 if (Lexer.is(AsmToken::Identifier)) {
7126 StringRef Value = Parser.getTok().getString();
7127 Parser.Lex();
7128
7129 if (Value != "xx") {
7130 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7131 return false;
7132 }
7133
7134 if (!isABI_O32()) {
7135 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7136 return false;
7137 }
7138
Daniel Sanders7e527422014-07-10 13:38:23 +00007139 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007140 if (ModuleLevelOptions) {
7141 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7142 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7143 } else {
7144 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7145 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7146 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007147 return true;
7148 }
7149
7150 if (Lexer.is(AsmToken::Integer)) {
7151 unsigned Value = Parser.getTok().getIntVal();
7152 Parser.Lex();
7153
7154 if (Value != 32 && Value != 64) {
7155 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7156 return false;
7157 }
7158
7159 if (Value == 32) {
7160 if (!isABI_O32()) {
7161 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7162 return false;
7163 }
7164
Daniel Sanders7e527422014-07-10 13:38:23 +00007165 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007166 if (ModuleLevelOptions) {
7167 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7168 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7169 } else {
7170 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7171 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7172 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007173 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007174 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007175 if (ModuleLevelOptions) {
7176 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7177 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7178 } else {
7179 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7180 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7181 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007182 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007183
Daniel Sanders7e527422014-07-10 13:38:23 +00007184 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007185 }
7186
7187 return false;
7188}
7189
Jack Carter0b744b32012-10-04 02:29:46 +00007190bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007191 // This returns false if this function recognizes the directive
7192 // regardless of whether it is successfully handles or reports an
7193 // error. Otherwise it returns true to give the generic parser a
7194 // chance at recognizing it.
7195
Rafael Espindola961d4692014-11-11 05:18:41 +00007196 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007197 StringRef IDVal = DirectiveID.getString();
7198
Nirav Dave996fc132016-05-05 14:15:46 +00007199 if (IDVal == ".cpload") {
7200 parseDirectiveCpLoad(DirectiveID.getLoc());
7201 return false;
7202 }
7203 if (IDVal == ".cprestore") {
7204 parseDirectiveCpRestore(DirectiveID.getLoc());
7205 return false;
7206 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007207 if (IDVal == ".dword") {
7208 parseDataDirective(8, DirectiveID.getLoc());
7209 return false;
7210 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007211 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007212 StringRef SymbolName;
7213
7214 if (Parser.parseIdentifier(SymbolName)) {
7215 reportParseError("expected identifier after .ent");
7216 return false;
7217 }
7218
7219 // There's an undocumented extension that allows an integer to
7220 // follow the name of the procedure which AFAICS is ignored by GAS.
7221 // Example: .ent foo,2
7222 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7223 if (getLexer().isNot(AsmToken::Comma)) {
7224 // Even though we accept this undocumented extension for compatibility
7225 // reasons, the additional integer argument does not actually change
7226 // the behaviour of the '.ent' directive, so we would like to discourage
7227 // its use. We do this by not referring to the extended version in
7228 // error messages which are not directly related to its use.
7229 reportParseError("unexpected token, expected end of statement");
7230 return false;
7231 }
7232 Parser.Lex(); // Eat the comma.
7233 const MCExpr *DummyNumber;
7234 int64_t DummyNumberVal;
7235 // If the user was explicitly trying to use the extended version,
7236 // we still give helpful extension-related error messages.
7237 if (Parser.parseExpression(DummyNumber)) {
7238 reportParseError("expected number after comma");
7239 return false;
7240 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007241 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007242 reportParseError("expected an absolute expression after comma");
7243 return false;
7244 }
7245 }
7246
7247 // If this is not the end of the statement, report an error.
7248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7249 reportParseError("unexpected token, expected end of statement");
7250 return false;
7251 }
7252
Jim Grosbach6f482002015-05-18 18:43:14 +00007253 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007254
7255 getTargetStreamer().emitDirectiveEnt(*Sym);
7256 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007257 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007258 return false;
7259 }
7260
Jack Carter07c818d2013-01-25 01:31:34 +00007261 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007262 StringRef SymbolName;
7263
7264 if (Parser.parseIdentifier(SymbolName)) {
7265 reportParseError("expected identifier after .end");
7266 return false;
7267 }
7268
7269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7270 reportParseError("unexpected token, expected end of statement");
7271 return false;
7272 }
7273
7274 if (CurrentFn == nullptr) {
7275 reportParseError(".end used without .ent");
7276 return false;
7277 }
7278
7279 if ((SymbolName != CurrentFn->getName())) {
7280 reportParseError(".end symbol does not match .ent symbol");
7281 return false;
7282 }
7283
7284 getTargetStreamer().emitDirectiveEnd(SymbolName);
7285 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007286 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007287 return false;
7288 }
7289
Jack Carter07c818d2013-01-25 01:31:34 +00007290 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007291 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7292 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007293 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007294 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7295 reportParseError("expected stack register");
7296 return false;
7297 }
7298
7299 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7300 if (!StackRegOpnd.isGPRAsmReg()) {
7301 reportParseError(StackRegOpnd.getStartLoc(),
7302 "expected general purpose register");
7303 return false;
7304 }
7305 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7306
7307 if (Parser.getTok().is(AsmToken::Comma))
7308 Parser.Lex();
7309 else {
7310 reportParseError("unexpected token, expected comma");
7311 return false;
7312 }
7313
7314 // Parse the frame size.
7315 const MCExpr *FrameSize;
7316 int64_t FrameSizeVal;
7317
7318 if (Parser.parseExpression(FrameSize)) {
7319 reportParseError("expected frame size value");
7320 return false;
7321 }
7322
Jim Grosbach13760bd2015-05-30 01:25:56 +00007323 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007324 reportParseError("frame size not an absolute expression");
7325 return false;
7326 }
7327
7328 if (Parser.getTok().is(AsmToken::Comma))
7329 Parser.Lex();
7330 else {
7331 reportParseError("unexpected token, expected comma");
7332 return false;
7333 }
7334
7335 // Parse the return register.
7336 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007337 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007338 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7339 reportParseError("expected return register");
7340 return false;
7341 }
7342
7343 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7344 if (!ReturnRegOpnd.isGPRAsmReg()) {
7345 reportParseError(ReturnRegOpnd.getStartLoc(),
7346 "expected general purpose register");
7347 return false;
7348 }
7349
7350 // If this is not the end of the statement, report an error.
7351 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7352 reportParseError("unexpected token, expected end of statement");
7353 return false;
7354 }
7355
7356 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7357 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007358 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007359 return false;
7360 }
7361
Jack Carter07c818d2013-01-25 01:31:34 +00007362 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007363 parseDirectiveSet();
7364 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007365 }
7366
Daniel Sandersd97a6342014-08-13 10:07:34 +00007367 if (IDVal == ".mask" || IDVal == ".fmask") {
7368 // .mask bitmask, frame_offset
7369 // bitmask: One bit for each register used.
7370 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7371 // first register is expected to be saved.
7372 // Examples:
7373 // .mask 0x80000000, -4
7374 // .fmask 0x80000000, -4
7375 //
Jack Carterbe332172012-09-07 00:48:02 +00007376
Daniel Sandersd97a6342014-08-13 10:07:34 +00007377 // Parse the bitmask
7378 const MCExpr *BitMask;
7379 int64_t BitMaskVal;
7380
7381 if (Parser.parseExpression(BitMask)) {
7382 reportParseError("expected bitmask value");
7383 return false;
7384 }
7385
Jim Grosbach13760bd2015-05-30 01:25:56 +00007386 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007387 reportParseError("bitmask not an absolute expression");
7388 return false;
7389 }
7390
7391 if (Parser.getTok().is(AsmToken::Comma))
7392 Parser.Lex();
7393 else {
7394 reportParseError("unexpected token, expected comma");
7395 return false;
7396 }
7397
7398 // Parse the frame_offset
7399 const MCExpr *FrameOffset;
7400 int64_t FrameOffsetVal;
7401
7402 if (Parser.parseExpression(FrameOffset)) {
7403 reportParseError("expected frame offset value");
7404 return false;
7405 }
7406
Jim Grosbach13760bd2015-05-30 01:25:56 +00007407 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007408 reportParseError("frame offset not an absolute expression");
7409 return false;
7410 }
7411
7412 // If this is not the end of the statement, report an error.
7413 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7414 reportParseError("unexpected token, expected end of statement");
7415 return false;
7416 }
7417
7418 if (IDVal == ".mask")
7419 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7420 else
7421 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007422 return false;
7423 }
7424
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007425 if (IDVal == ".nan")
7426 return parseDirectiveNaN();
7427
Jack Carter07c818d2013-01-25 01:31:34 +00007428 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007429 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007430 return false;
7431 }
7432
Rafael Espindolab59fb732014-03-28 18:50:26 +00007433 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007434 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007435 return false;
7436 }
7437
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007438 if (IDVal == ".dtprelword") {
7439 parseDirectiveDtpRelWord();
7440 return false;
7441 }
7442
7443 if (IDVal == ".dtpreldword") {
7444 parseDirectiveDtpRelDWord();
7445 return false;
7446 }
7447
7448 if (IDVal == ".tprelword") {
7449 parseDirectiveTpRelWord();
7450 return false;
7451 }
7452
7453 if (IDVal == ".tpreldword") {
7454 parseDirectiveTpRelDWord();
7455 return false;
7456 }
7457
Jack Carter07c818d2013-01-25 01:31:34 +00007458 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007459 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007460 return false;
7461 }
7462
Scott Egertond1aeb052016-02-15 16:11:51 +00007463 if (IDVal == ".hword") {
7464 parseDataDirective(2, DirectiveID.getLoc());
7465 return false;
7466 }
7467
Nirav Dave996fc132016-05-05 14:15:46 +00007468 if (IDVal == ".option") {
7469 parseDirectiveOption();
7470 return false;
7471 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007472
7473 if (IDVal == ".abicalls") {
7474 getTargetStreamer().emitDirectiveAbiCalls();
7475 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007476 Error(Parser.getTok().getLoc(),
7477 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007478 }
7479 return false;
7480 }
7481
Nirav Dave996fc132016-05-05 14:15:46 +00007482 if (IDVal == ".cpsetup") {
7483 parseDirectiveCPSetup();
7484 return false;
7485 }
7486 if (IDVal == ".cpreturn") {
7487 parseDirectiveCPReturn();
7488 return false;
7489 }
7490 if (IDVal == ".module") {
7491 parseDirectiveModule();
7492 return false;
7493 }
7494 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7495 parseInternalDirectiveReallowModule();
7496 return false;
7497 }
7498 if (IDVal == ".insn") {
7499 parseInsnDirective();
7500 return false;
7501 }
7502 if (IDVal == ".sbss") {
7503 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7504 return false;
7505 }
7506 if (IDVal == ".sdata") {
7507 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7508 return false;
7509 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007510
Rafael Espindola870c4e92012-01-11 03:56:41 +00007511 return true;
7512}
7513
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007514bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7515 // If this is not the end of the statement, report an error.
7516 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7517 reportParseError("unexpected token, expected end of statement");
7518 return false;
7519 }
7520
7521 getTargetStreamer().reallowModuleDirective();
7522
7523 getParser().Lex(); // Eat EndOfStatement token.
7524 return false;
7525}
7526
Rafael Espindola870c4e92012-01-11 03:56:41 +00007527extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007528 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7529 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7530 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
7531 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00007532}
Jack Carterb4dbc172012-09-05 23:34:03 +00007533
7534#define GET_REGISTER_MATCHER
7535#define GET_MATCHER_IMPLEMENTATION
7536#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00007537
7538bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
7539 // Find the appropriate table for this asm variant.
7540 const MatchEntry *Start, *End;
7541 switch (VariantID) {
7542 default: llvm_unreachable("invalid variant!");
7543 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
7544 }
7545 // Search the table.
7546 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
7547 return MnemonicRange.first != MnemonicRange.second;
7548}