blob: 345b081500a42f7498f17a2c07d2f722f7c87637 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000307 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
308 const MCSubtargetInfo *STI);
309
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000310 bool reportParseError(Twine ErrorMsg);
311 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000312
Jack Carterb5cf5902013-04-17 00:18:04 +0000313 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000314
315 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000316 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000317 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000318 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000319 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000320 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000321 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000322 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000323 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000324 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000325 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000326 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000327 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000328 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000329 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000330
331 bool parseSetAtDirective();
332 bool parseSetNoAtDirective();
333 bool parseSetMacroDirective();
334 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000335 bool parseSetMsaDirective();
336 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000337 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000338 bool parseSetReorderDirective();
339 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000340 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000341 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000342 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000343 bool parseSetOddSPRegDirective();
344 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000345 bool parseSetPopDirective();
346 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000347 bool parseSetSoftFloatDirective();
348 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000349 bool parseSetMtDirective();
350 bool parseSetNoMtDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000351
Jack Carterd76b2372013-03-21 21:44:16 +0000352 bool parseSetAssignment();
353
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000354 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000355 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000356 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000357 bool parseDirectiveDtpRelWord();
358 bool parseDirectiveDtpRelDWord();
359 bool parseDirectiveTpRelWord();
360 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000361 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000362 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000363 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
364 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000365
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000366 bool parseInternalDirectiveReallowModule();
367
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000368 bool eatComma(StringRef ErrorStr);
369
Jack Carter1ac53222013-02-20 23:11:17 +0000370 int matchCPURegisterName(StringRef Symbol);
371
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000372 int matchHWRegsRegisterName(StringRef Symbol);
373
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000374 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000375
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000376 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000377
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000378 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000379
Jack Carter5dc8ac92013-09-25 23:50:44 +0000380 int matchMSA128RegisterName(StringRef Name);
381
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000382 int matchMSA128CtrlRegisterName(StringRef Name);
383
Jack Carterd0bd6422013-04-18 00:41:53 +0000384 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000385
Toma Tabacu89a712b2015-04-15 10:48:56 +0000386 /// Returns the internal register number for the current AT. Also checks if
387 /// the current AT is unavailable (set to $0) and gives an error if it is.
388 /// This should be used in pseudo-instruction expansions which need AT.
389 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000390
Simon Dardis3aa8a902017-02-06 12:43:46 +0000391 bool canUseATReg();
392
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000393 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
394 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000395
396 // Helper function that checks if the value of a vector index is within the
397 // boundaries of accepted values for each RegisterKind
398 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
399 bool validateMSAIndex(int Val, int RegKind);
400
Daniel Sandersf0df2212014-08-04 12:20:00 +0000401 // Selects a new architecture by updating the FeatureBits with the necessary
402 // info including implied dependencies.
403 // Internally, it clears all the feature bits related to *any* architecture
404 // and selects the new one using the ToggleFeature functionality of the
405 // MCSubtargetInfo object that handles implied dependencies. The reason we
406 // clear all the arch related bits manually is because ToggleFeature only
407 // clears the features that imply the feature being cleared and not the
408 // features implied by the feature being cleared. This is easier to see
409 // with an example:
410 // --------------------------------------------------
411 // | Feature | Implies |
412 // | -------------------------------------------------|
413 // | FeatureMips1 | None |
414 // | FeatureMips2 | FeatureMips1 |
415 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
416 // | FeatureMips4 | FeatureMips3 |
417 // | ... | |
418 // --------------------------------------------------
419 //
420 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
421 // FeatureMipsGP64 | FeatureMips1)
422 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
423 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000424 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000425 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000426 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
427 STI.setFeatureBits(FeatureBits);
428 setAvailableFeatures(
429 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000430 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000431 }
432
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000433 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000434 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000435 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000436 setAvailableFeatures(
437 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000438 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000439 }
440 }
441
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000442 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000443 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000444 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000445 setAvailableFeatures(
446 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000447 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000448 }
449 }
450
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000451 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
452 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000453 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000454 }
455
456 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
457 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000458 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000459 }
460
Rafael Espindola870c4e92012-01-11 03:56:41 +0000461public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000462 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000463 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000464 Match_RequiresDifferentOperands,
465 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000466 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000467 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000468 Match_NonZeroOperandForSync,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000469 Match_RequiresPosSizeRange0_32,
470 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000471 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000472#define GET_OPERAND_DIAGNOSTIC_TYPES
473#include "MipsGenAsmMatcher.inc"
474#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000475 };
476
Akira Hatanakab11ef082015-11-14 06:35:56 +0000477 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000478 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000479 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000480 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
481 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000482 MCAsmParserExtension::Initialize(parser);
483
Toma Tabacu11e14a92015-04-21 11:50:52 +0000484 parser.addAliasForDirective(".asciiz", ".asciz");
485
Jack Carterb4dbc172012-09-05 23:34:03 +0000486 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000488
Toma Tabacu9db22db2014-09-09 10:15:38 +0000489 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000490 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000491 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000492
Toma Tabacu9db22db2014-09-09 10:15:38 +0000493 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000494 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000496
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 getTargetStreamer().updateABIInfo(*this);
498
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000499 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000500 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000501
502 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000503
Rafael Espindola699281c2016-05-18 11:58:50 +0000504 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000505
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000506 IsCpRestoreSet = false;
507 CpRestoreOffset = -1;
508
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000509 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000510 if ((TheTriple.getArch() == Triple::mips) ||
511 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000512 IsLittleEndian = false;
513 else
514 IsLittleEndian = true;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000515
516 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
517 report_fatal_error("microMIPS64R6 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000518 }
519
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000520 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
521 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
522
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool isGP64bit() const {
524 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
525 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000526
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000527 bool isFP64bit() const {
528 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
529 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000530
Eric Christophera5762812015-01-26 17:33:46 +0000531 const MipsABIInfo &getABI() const { return ABI; }
532 bool isABI_N32() const { return ABI.IsN32(); }
533 bool isABI_N64() const { return ABI.IsN64(); }
534 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 bool isABI_FPXX() const {
536 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
537 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000539 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000541 }
542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000546
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000547 bool hasMips1() const {
548 return getSTI().getFeatureBits()[Mips::FeatureMips1];
549 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000550
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000551 bool hasMips2() const {
552 return getSTI().getFeatureBits()[Mips::FeatureMips2];
553 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000554
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000555 bool hasMips3() const {
556 return getSTI().getFeatureBits()[Mips::FeatureMips3];
557 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000558
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000559 bool hasMips4() const {
560 return getSTI().getFeatureBits()[Mips::FeatureMips4];
561 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000562
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000563 bool hasMips5() const {
564 return getSTI().getFeatureBits()[Mips::FeatureMips5];
565 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000566
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000567 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000568 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000570
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000571 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000572 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000574
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000576 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000577 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000578
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000579 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000580 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000581 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000582
Daniel Sanders17793142015-02-18 16:24:50 +0000583 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000584 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000585 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000586
Daniel Sanders17793142015-02-18 16:24:50 +0000587 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000588 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000590
Daniel Sanders17793142015-02-18 16:24:50 +0000591 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000592 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000593 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000594
Daniel Sanders17793142015-02-18 16:24:50 +0000595 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000598
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000599 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000601 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000602
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000603 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000605 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000606
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000607 bool hasDSP() const {
608 return getSTI().getFeatureBits()[Mips::FeatureDSP];
609 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000610
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000611 bool hasDSPR2() const {
612 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
613 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000614
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000615 bool hasDSPR3() const {
616 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
617 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000618
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000619 bool hasMSA() const {
620 return getSTI().getFeatureBits()[Mips::FeatureMSA];
621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000622
Kai Nackee0245392015-01-27 19:11:28 +0000623 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000624 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000625 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000626
Daniel Sandersa6994442015-08-18 12:33:54 +0000627 bool inPicMode() {
628 return IsPicEnabled;
629 }
630
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000631 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000632 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000633 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000634
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000635 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000636 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000637 }
638
Eric Christophere8ae3e32015-05-07 23:10:21 +0000639 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000640 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000641 }
Simon Dardisae719c52017-07-11 18:03:20 +0000642 bool hasMT() const {
643 return getSTI().getFeatureBits()[Mips::FeatureMT];
644 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000645
Toma Tabacud9d344b2015-04-27 14:05:04 +0000646 /// Warn if RegIndex is the same as the current AT.
647 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000648
649 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000650
651 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000652
653 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
654 AsmToken::TokenKind OperatorToken,
655 MCContext &Ctx) override {
656 switch(OperatorToken) {
657 default:
658 llvm_unreachable("Unknown token");
659 return nullptr;
660 case AsmToken::PercentCall16:
661 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
662 case AsmToken::PercentCall_Hi:
663 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
664 case AsmToken::PercentCall_Lo:
665 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
666 case AsmToken::PercentDtprel_Hi:
667 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
668 case AsmToken::PercentDtprel_Lo:
669 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
670 case AsmToken::PercentGot:
671 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
672 case AsmToken::PercentGot_Disp:
673 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
674 case AsmToken::PercentGot_Hi:
675 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
676 case AsmToken::PercentGot_Lo:
677 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
678 case AsmToken::PercentGot_Ofst:
679 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
680 case AsmToken::PercentGot_Page:
681 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
682 case AsmToken::PercentGottprel:
683 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
684 case AsmToken::PercentGp_Rel:
685 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
686 case AsmToken::PercentHi:
687 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
688 case AsmToken::PercentHigher:
689 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
690 case AsmToken::PercentHighest:
691 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
692 case AsmToken::PercentLo:
693 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
694 case AsmToken::PercentNeg:
695 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
696 case AsmToken::PercentPcrel_Hi:
697 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
698 case AsmToken::PercentPcrel_Lo:
699 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
700 case AsmToken::PercentTlsgd:
701 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
702 case AsmToken::PercentTlsldm:
703 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
704 case AsmToken::PercentTprel_Hi:
705 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
706 case AsmToken::PercentTprel_Lo:
707 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
708 }
709 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000710};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000711
712/// MipsOperand - Instances of this class represent a parsed Mips machine
713/// instruction.
714class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000715public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000716 /// Broad categories of register classes
717 /// The exact class is finalized by the render method.
718 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000719 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000720 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000721 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 RegKind_FCC = 4, /// FCC
723 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
724 RegKind_MSACtrl = 16, /// MSA control registers
725 RegKind_COP2 = 32, /// COP2
726 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
727 /// context).
728 RegKind_CCR = 128, /// CCR
729 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000730 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000731 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 /// Potentially any (e.g. $1)
733 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
734 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000735 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000736 };
737
738private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000739 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000740 k_Immediate, /// An immediate (possibly involving symbol references)
741 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000742 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000743 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000744 k_RegList, /// A physical register list
745 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000746 } Kind;
747
David Blaikie960ea3f2014-06-08 16:18:35 +0000748public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000749 MipsOperand(KindTy K, MipsAsmParser &Parser)
750 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
751
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000752 ~MipsOperand() override {
753 switch (Kind) {
754 case k_Immediate:
755 break;
756 case k_Memory:
757 delete Mem.Base;
758 break;
759 case k_RegList:
760 delete RegList.List;
761 case k_RegisterIndex:
762 case k_Token:
763 case k_RegPair:
764 break;
765 }
766 }
767
David Blaikie960ea3f2014-06-08 16:18:35 +0000768private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000769 /// For diagnostics, and checking the assembler temporary
770 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000771
Eric Christopher8996c5d2013-03-15 00:42:55 +0000772 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000773 const char *Data;
774 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000775 };
776
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 struct RegIdxOp {
778 unsigned Index; /// Index into the register class
779 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000780 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000782 };
783
784 struct ImmOp {
785 const MCExpr *Val;
786 };
787
788 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000790 const MCExpr *Off;
791 };
792
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000793 struct RegListOp {
794 SmallVector<unsigned, 10> *List;
795 };
796
Jack Carterb4dbc172012-09-05 23:34:03 +0000797 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000798 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000800 struct ImmOp Imm;
801 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000802 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000803 };
804
805 SMLoc StartLoc, EndLoc;
806
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000808 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
809 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000810 const MCRegisterInfo *RegInfo,
811 SMLoc S, SMLoc E,
812 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000813 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 Op->RegIdx.Index = Index;
815 Op->RegIdx.RegInfo = RegInfo;
816 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000817 Op->RegIdx.Tok.Data = Str.data();
818 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 Op->StartLoc = S;
820 Op->EndLoc = E;
821 return Op;
822 }
823
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000824public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 /// Coerce the register to GPR32 and return the real register for the current
826 /// target.
827 unsigned getGPR32Reg() const {
828 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000829 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 unsigned ClassID = Mips::GPR32RegClassID;
831 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000832 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000833
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000834 /// Coerce the register to GPR32 and return the real register for the current
835 /// target.
836 unsigned getGPRMM16Reg() const {
837 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
838 unsigned ClassID = Mips::GPR32RegClassID;
839 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
840 }
841
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000842 /// Coerce the register to GPR64 and return the real register for the current
843 /// target.
844 unsigned getGPR64Reg() const {
845 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
846 unsigned ClassID = Mips::GPR64RegClassID;
847 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000848 }
849
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850private:
851 /// Coerce the register to AFGR64 and return the real register for the current
852 /// target.
853 unsigned getAFGR64Reg() const {
854 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
855 if (RegIdx.Index % 2 != 0)
856 AsmParser.Warning(StartLoc, "Float register should be even.");
857 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
858 .getRegister(RegIdx.Index / 2);
859 }
860
861 /// Coerce the register to FGR64 and return the real register for the current
862 /// target.
863 unsigned getFGR64Reg() const {
864 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
865 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
866 .getRegister(RegIdx.Index);
867 }
868
869 /// Coerce the register to FGR32 and return the real register for the current
870 /// target.
871 unsigned getFGR32Reg() const {
872 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
873 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
874 .getRegister(RegIdx.Index);
875 }
876
877 /// Coerce the register to FGRH32 and return the real register for the current
878 /// target.
879 unsigned getFGRH32Reg() const {
880 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
881 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
882 .getRegister(RegIdx.Index);
883 }
884
885 /// Coerce the register to FCC and return the real register for the current
886 /// target.
887 unsigned getFCCReg() const {
888 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
889 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
890 .getRegister(RegIdx.Index);
891 }
892
893 /// Coerce the register to MSA128 and return the real register for the current
894 /// target.
895 unsigned getMSA128Reg() const {
896 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
897 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
898 // identical
899 unsigned ClassID = Mips::MSA128BRegClassID;
900 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
901 }
902
903 /// Coerce the register to MSACtrl and return the real register for the
904 /// current target.
905 unsigned getMSACtrlReg() const {
906 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
907 unsigned ClassID = Mips::MSACtrlRegClassID;
908 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
909 }
910
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000911 /// Coerce the register to COP0 and return the real register for the
912 /// current target.
913 unsigned getCOP0Reg() const {
914 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
915 unsigned ClassID = Mips::COP0RegClassID;
916 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
917 }
918
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000919 /// Coerce the register to COP2 and return the real register for the
920 /// current target.
921 unsigned getCOP2Reg() const {
922 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
923 unsigned ClassID = Mips::COP2RegClassID;
924 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
925 }
926
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000927 /// Coerce the register to COP3 and return the real register for the
928 /// current target.
929 unsigned getCOP3Reg() const {
930 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
931 unsigned ClassID = Mips::COP3RegClassID;
932 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
933 }
934
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 /// Coerce the register to ACC64DSP and return the real register for the
936 /// current target.
937 unsigned getACC64DSPReg() const {
938 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
939 unsigned ClassID = Mips::ACC64DSPRegClassID;
940 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
941 }
942
943 /// Coerce the register to HI32DSP and return the real register for the
944 /// current target.
945 unsigned getHI32DSPReg() const {
946 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
947 unsigned ClassID = Mips::HI32DSPRegClassID;
948 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
949 }
950
951 /// Coerce the register to LO32DSP and return the real register for the
952 /// current target.
953 unsigned getLO32DSPReg() const {
954 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
955 unsigned ClassID = Mips::LO32DSPRegClassID;
956 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
957 }
958
959 /// Coerce the register to CCR and return the real register for the
960 /// current target.
961 unsigned getCCRReg() const {
962 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
963 unsigned ClassID = Mips::CCRRegClassID;
964 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
965 }
966
967 /// Coerce the register to HWRegs and return the real register for the
968 /// current target.
969 unsigned getHWRegsReg() const {
970 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
971 unsigned ClassID = Mips::HWRegsRegClassID;
972 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
973 }
974
975public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000976 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000977 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000978 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000979 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000980 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000981 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000982 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000983 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000984 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000985
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 void addRegOperands(MCInst &Inst, unsigned N) const {
987 llvm_unreachable("Use a custom parser instead");
988 }
989
Daniel Sanders21bce302014-04-01 12:35:23 +0000990 /// Render the operand to an MCInst as a GPR32
991 /// Asserts if the wrong number of operands are requested, or the operand
992 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000993 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
995 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
996 }
997
998 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
999 assert(N == 1 && "Invalid number of operands!");
1000 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1001 }
1002
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001003 void addGPR32AsmRegOperands(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(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 }
1007
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001008 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1009 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001010 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001011 }
1012
Jozef Kolek1904fa22014-11-24 14:25:53 +00001013 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1014 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001015 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001016 }
1017
Zoran Jovanovic41688672015-02-10 16:36:20 +00001018 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1019 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001020 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001021 }
1022
Daniel Sanders21bce302014-04-01 12:35:23 +00001023 /// Render the operand to an MCInst as a GPR64
1024 /// Asserts if the wrong number of operands are requested, or the operand
1025 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001026 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1027 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001028 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001029 }
1030
1031 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 }
1035
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001036 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1037 assert(N == 1 && "Invalid number of operands!");
1038 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1039 }
1040
1041 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1042 assert(N == 1 && "Invalid number of operands!");
1043 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1044 }
1045
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1047 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001048 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001049 }
1050
1051 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1052 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001053 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001054 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001055 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001056 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001057 AsmParser.getParser().printError(
1058 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1059 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 }
1061
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001062 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
1064 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1065 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1066 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1067 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1068 "registers");
1069 }
1070
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 void addFGRH32AsmRegOperands(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(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 }
1075
1076 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1077 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001078 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001079 }
1080
1081 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001084 }
1085
1086 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001089 }
1090
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001091 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1092 assert(N == 1 && "Invalid number of operands!");
1093 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1094 }
1095
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001099 }
1100
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001101 void addCOP3AsmRegOperands(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(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001104 }
1105
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001106 void addACC64DSPAsmRegOperands(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(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001109 }
1110
1111 void addHI32DSPAsmRegOperands(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(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001114 }
1115
1116 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001118 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001119 }
1120
1121 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001123 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 }
1125
1126 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001128 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001129 }
1130
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001131 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001132 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001134 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001135 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001136 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001137 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001138 Inst.addOperand(MCOperand::createImm(Imm));
1139 }
1140
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001141 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001142 void addSImmOperands(MCInst &Inst, unsigned N) const {
1143 if (isImm() && !isConstantImm()) {
1144 addExpr(Inst, getImm());
1145 return;
1146 }
1147 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1148 }
1149
1150 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001151 void addUImmOperands(MCInst &Inst, unsigned N) const {
1152 if (isImm() && !isConstantImm()) {
1153 addExpr(Inst, getImm());
1154 return;
1155 }
1156 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1157 }
1158
Daniel Sanders78e89022016-03-11 11:37:50 +00001159 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1160 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 int64_t Imm = getConstantImm() - Offset;
1163 Imm = SignExtend64<Bits>(Imm);
1164 Imm += Offset;
1165 Imm += AdjustOffset;
1166 Inst.addOperand(MCOperand::createImm(Imm));
1167 }
1168
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001169 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001170 assert(N == 1 && "Invalid number of operands!");
1171 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001173 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001174
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001175 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001176 assert(N == 2 && "Invalid number of operands!");
1177
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001178 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1179 ? getMemBase()->getGPR64Reg()
1180 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001181
1182 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001184 }
1185
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001186 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 2 && "Invalid number of operands!");
1188
Jim Grosbache9119e42015-05-13 18:37:00 +00001189 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001190
1191 const MCExpr *Expr = getMemOff();
1192 addExpr(Inst, Expr);
1193 }
1194
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001195 void addRegListOperands(MCInst &Inst, unsigned N) const {
1196 assert(N == 1 && "Invalid number of operands!");
1197
1198 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001199 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001200 }
1201
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001202 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1203 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001204 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001205 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001206 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1207 Inst.addOperand(MCOperand::createReg(
1208 RegIdx.RegInfo->getRegClass(
1209 AsmParser.getABI().AreGprs64bit()
1210 ? Mips::GPR64RegClassID
1211 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1212 Inst.addOperand(MCOperand::createReg(
1213 RegIdx.RegInfo->getRegClass(
1214 AsmParser.getABI().AreGprs64bit()
1215 ? Mips::GPR64RegClassID
1216 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001217 }
1218
Zoran Jovanovic41688672015-02-10 16:36:20 +00001219 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 2 && "Invalid number of operands!");
1221 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001222 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001223 }
1224
Craig Topper56c590a2014-04-29 07:58:02 +00001225 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001226 // As a special case until we sort out the definition of div/divu, accept
1227 // $0/$zero here so that MCK_ZERO works correctly.
1228 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001230
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001231 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001232 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001233
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001235 int64_t Res;
1236 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001238
Daniel Sanders52da7af2015-11-06 12:11:03 +00001239 bool isConstantImmz() const {
1240 return isConstantImm() && getConstantImm() == 0;
1241 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001242
Daniel Sandersea4f6532015-11-06 12:22:31 +00001243 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1244 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1245 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001246
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001247 template <unsigned Bits> bool isSImm() const {
1248 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1249 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001250
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001251 template <unsigned Bits> bool isUImm() const {
1252 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1253 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001254
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001255 template <unsigned Bits> bool isAnyImm() const {
1256 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1257 isUInt<Bits>(getConstantImm()))
1258 : isImm();
1259 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001260
Daniel Sanders78e89022016-03-11 11:37:50 +00001261 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1262 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001263 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001264
Hrvoje Varga46458d02016-02-25 12:53:29 +00001265 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1266 return isConstantImm() && getConstantImm() >= Bottom &&
1267 getConstantImm() <= Top;
1268 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001269
Craig Topper56c590a2014-04-29 07:58:02 +00001270 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001271 // Note: It's not possible to pretend that other operand kinds are tokens.
1272 // The matcher emitter checks tokens first.
1273 return Kind == k_Token;
1274 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001275
Craig Topper56c590a2014-04-29 07:58:02 +00001276 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001277
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001278 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001279 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001280 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001281
Simon Dardis4ccda502016-05-27 13:56:36 +00001282 // Allow relocation operators.
1283 // FIXME: This predicate and others need to look through binary expressions
1284 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001285 template <unsigned Bits, unsigned ShiftAmount = 0>
1286 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001287 if (!isMem())
1288 return false;
1289 if (!getMemBase()->isGPRAsmReg())
1290 return false;
1291 if (isa<MCTargetExpr>(getMemOff()) ||
1292 (isConstantMemOff() &&
1293 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1294 return true;
1295 MCValue Res;
1296 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1297 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001298 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001299
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001300 bool isMemWithGRPMM16Base() const {
1301 return isMem() && getMemBase()->isMM16AsmReg();
1302 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001303
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001304 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1305 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1306 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1307 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001308
Jozef Kolek12c69822014-12-23 16:16:33 +00001309 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1310 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1311 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1312 && (getMemBase()->getGPR32Reg() == Mips::SP);
1313 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001314
Daniel Sanderse473dc92016-05-09 13:38:25 +00001315 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1316 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1317 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1318 && (getMemBase()->getGPR32Reg() == Mips::GP);
1319 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001320
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001321 template <unsigned Bits, unsigned ShiftLeftAmount>
1322 bool isScaledUImm() const {
1323 return isConstantImm() &&
1324 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001325 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001326
Daniel Sanders97297772016-03-22 14:40:00 +00001327 template <unsigned Bits, unsigned ShiftLeftAmount>
1328 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001329 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1330 return true;
1331 // Operand can also be a symbol or symbol plus offset in case of relocations.
1332 if (Kind != k_Immediate)
1333 return false;
1334 MCValue Res;
1335 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1336 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001337 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001338
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001339 bool isRegList16() const {
1340 if (!isRegList())
1341 return false;
1342
1343 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001344 if (Size < 2 || Size > 5)
1345 return false;
1346
1347 unsigned R0 = RegList.List->front();
1348 unsigned R1 = RegList.List->back();
1349 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1350 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001351 return false;
1352
1353 int PrevReg = *RegList.List->begin();
1354 for (int i = 1; i < Size - 1; i++) {
1355 int Reg = (*(RegList.List))[i];
1356 if ( Reg != PrevReg + 1)
1357 return false;
1358 PrevReg = Reg;
1359 }
1360
1361 return true;
1362 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001363
Vladimir Medic2b953d02013-10-01 09:48:56 +00001364 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001365
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001366 bool isLSAImm() const {
1367 if (!isConstantImm())
1368 return false;
1369 int64_t Val = getConstantImm();
1370 return 1 <= Val && Val <= 4;
1371 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001372
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001373 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001374
Zoran Jovanovic41688672015-02-10 16:36:20 +00001375 bool isMovePRegPair() const {
1376 if (Kind != k_RegList || RegList.List->size() != 2)
1377 return false;
1378
1379 unsigned R0 = RegList.List->front();
1380 unsigned R1 = RegList.List->back();
1381
1382 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1383 (R0 == Mips::A1 && R1 == Mips::A3) ||
1384 (R0 == Mips::A2 && R1 == Mips::A3) ||
1385 (R0 == Mips::A0 && R1 == Mips::S5) ||
1386 (R0 == Mips::A0 && R1 == Mips::S6) ||
1387 (R0 == Mips::A0 && R1 == Mips::A1) ||
1388 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001389 (R0 == Mips::A0 && R1 == Mips::A3) ||
1390 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1391 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1392 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1393 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1394 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1395 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1396 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1397 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001398 return true;
1399
1400 return false;
1401 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001402
1403 StringRef getToken() const {
1404 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001405 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001406 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001407
Zlatko Buljanba553a62016-05-09 08:07:28 +00001408 bool isRegPair() const {
1409 return Kind == k_RegPair && RegIdx.Index <= 30;
1410 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001411
Craig Topper56c590a2014-04-29 07:58:02 +00001412 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001413 // As a special case until we sort out the definition of div/divu, accept
1414 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1416 RegIdx.Kind & RegKind_GPR)
1417 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001418
Daniel Sanders976d9382016-07-05 13:38:40 +00001419 llvm_unreachable("Invalid access!");
1420 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001421 }
1422
Jack Carterb4dbc172012-09-05 23:34:03 +00001423 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001424 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001425 return Imm.Val;
1426 }
1427
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001428 int64_t getConstantImm() const {
1429 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001430 int64_t Value = 0;
1431 (void)Val->evaluateAsAbsolute(Value);
1432 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001433 }
1434
1435 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001436 assert((Kind == k_Memory) && "Invalid access!");
1437 return Mem.Base;
1438 }
1439
1440 const MCExpr *getMemOff() const {
1441 assert((Kind == k_Memory) && "Invalid access!");
1442 return Mem.Off;
1443 }
1444
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001445 int64_t getConstantMemOff() const {
1446 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1447 }
1448
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001449 const SmallVectorImpl<unsigned> &getRegList() const {
1450 assert((Kind == k_RegList) && "Invalid access!");
1451 return *(RegList.List);
1452 }
1453
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001454 unsigned getRegPair() const {
1455 assert((Kind == k_RegPair) && "Invalid access!");
1456 return RegIdx.Index;
1457 }
1458
David Blaikie960ea3f2014-06-08 16:18:35 +00001459 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1460 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001461 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001462 Op->Tok.Data = Str.data();
1463 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001464 Op->StartLoc = S;
1465 Op->EndLoc = S;
1466 return Op;
1467 }
1468
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001469 /// Create a numeric register (e.g. $1). The exact register remains
1470 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001471 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001472 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1473 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001474 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001475 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001476 }
1477
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001478 /// Create a register that is definitely a GPR.
1479 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001480 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001481 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1482 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1483 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001484 }
1485
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001486 /// Create a register that is definitely a FGR.
1487 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001488 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001489 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1490 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1491 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001492 }
1493
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001494 /// Create a register that is definitely a HWReg.
1495 /// This is typically only used for named registers such as $hwr_cpunum.
1496 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001497 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001498 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001499 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001500 }
1501
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001502 /// Create a register that is definitely an FCC.
1503 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001504 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001505 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1506 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1507 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001508 }
1509
1510 /// Create a register that is definitely an ACC.
1511 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001512 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001513 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1514 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1515 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001516 }
1517
1518 /// Create a register that is definitely an MSA128.
1519 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001520 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001521 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1522 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1523 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001524 }
1525
1526 /// Create a register that is definitely an MSACtrl.
1527 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001528 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001529 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1530 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1531 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001532 }
1533
David Blaikie960ea3f2014-06-08 16:18:35 +00001534 static std::unique_ptr<MipsOperand>
1535 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001536 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001537 Op->Imm.Val = Val;
1538 Op->StartLoc = S;
1539 Op->EndLoc = E;
1540 return Op;
1541 }
1542
David Blaikie960ea3f2014-06-08 16:18:35 +00001543 static std::unique_ptr<MipsOperand>
1544 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1545 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001546 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001547 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001548 Op->Mem.Off = Off;
1549 Op->StartLoc = S;
1550 Op->EndLoc = E;
1551 return Op;
1552 }
1553
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001554 static std::unique_ptr<MipsOperand>
1555 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1556 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001557 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001558
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001559 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001560 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001561 Op->StartLoc = StartLoc;
1562 Op->EndLoc = EndLoc;
1563 return Op;
1564 }
1565
Daniel Sandersd044e492016-05-09 13:10:57 +00001566 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1567 SMLoc S, SMLoc E,
1568 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001569 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001570 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001571 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1572 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001573 Op->StartLoc = S;
1574 Op->EndLoc = E;
1575 return Op;
1576 }
1577
Simon Dardis509da1a2017-02-13 16:06:48 +00001578 bool isGPRZeroAsmReg() const {
1579 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1580 }
1581
1582 bool isGPRNonZeroAsmReg() const {
1583 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1584 RegIdx.Index <= 31;
1585 }
1586
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001587 bool isGPRAsmReg() const {
1588 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001589 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001590
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001591 bool isMM16AsmReg() const {
1592 if (!(isRegIdx() && RegIdx.Kind))
1593 return false;
1594 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1595 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001596
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001597 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001598 bool isMM16AsmRegZero() const {
1599 if (!(isRegIdx() && RegIdx.Kind))
1600 return false;
1601 return (RegIdx.Index == 0 ||
1602 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1603 RegIdx.Index == 17);
1604 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001605
Zoran Jovanovic41688672015-02-10 16:36:20 +00001606 bool isMM16AsmRegMoveP() const {
1607 if (!(isRegIdx() && RegIdx.Kind))
1608 return false;
1609 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1610 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1611 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001613 bool isFGRAsmReg() const {
1614 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1615 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001616 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001617
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001618 bool isStrictlyFGRAsmReg() const {
1619 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1620 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1621 }
1622
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001623 bool isHWRegsAsmReg() const {
1624 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001626
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001627 bool isCCRAsmReg() const {
1628 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001632 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1633 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001634 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001635 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001636
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001637 bool isACCAsmReg() const {
1638 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001639 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001640
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001641 bool isCOP0AsmReg() const {
1642 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1643 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001644
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001645 bool isCOP2AsmReg() const {
1646 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001647 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001648
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001649 bool isCOP3AsmReg() const {
1650 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1651 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001652
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 bool isMSA128AsmReg() const {
1654 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001655 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001656
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001657 bool isMSACtrlAsmReg() const {
1658 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001659 }
1660
Jack Carterb4dbc172012-09-05 23:34:03 +00001661 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001662 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001663 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001664 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001665
Craig Topper56c590a2014-04-29 07:58:02 +00001666 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001667 switch (Kind) {
1668 case k_Immediate:
1669 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001670 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001671 OS << ">";
1672 break;
1673 case k_Memory:
1674 OS << "Mem<";
1675 Mem.Base->print(OS);
1676 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001677 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001678 OS << ">";
1679 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001680 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001681 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1682 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001683 break;
1684 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001685 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001686 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001687 case k_RegList:
1688 OS << "RegList< ";
1689 for (auto Reg : (*RegList.List))
1690 OS << Reg << " ";
1691 OS << ">";
1692 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001693 case k_RegPair:
1694 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1695 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001696 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001697 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001698
1699 bool isValidForTie(const MipsOperand &Other) const {
1700 if (Kind != Other.Kind)
1701 return false;
1702
1703 switch (Kind) {
1704 default:
1705 llvm_unreachable("Unexpected kind");
1706 return false;
1707 case k_RegisterIndex: {
1708 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1709 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1710 return Token == OtherToken;
1711 }
1712 }
1713 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001714}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001715
1716} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001717
Jack Carter9e65aa32013-03-22 00:05:30 +00001718namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001719
Jack Carter9e65aa32013-03-22 00:05:30 +00001720extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001721
1722} // end namespace llvm
1723
Jack Carter9e65aa32013-03-22 00:05:30 +00001724static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1725 return MipsInsts[Opcode];
1726}
1727
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001728static bool hasShortDelaySlot(unsigned Opcode) {
1729 switch (Opcode) {
1730 case Mips::JALS_MM:
1731 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001732 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001733 case Mips::BGEZALS_MM:
1734 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001735 return true;
1736 default:
1737 return false;
1738 }
1739}
1740
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001741static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1742 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1743 return &SRExpr->getSymbol();
1744 }
1745
1746 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1747 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1748 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1749
1750 if (LHSSym)
1751 return LHSSym;
1752
1753 if (RHSSym)
1754 return RHSSym;
1755
1756 return nullptr;
1757 }
1758
1759 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1760 return getSingleMCSymbol(UExpr->getSubExpr());
1761
1762 return nullptr;
1763}
1764
1765static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1766 if (isa<MCSymbolRefExpr>(Expr))
1767 return 1;
1768
1769 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1770 return countMCSymbolRefExpr(BExpr->getLHS()) +
1771 countMCSymbolRefExpr(BExpr->getRHS());
1772
1773 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1774 return countMCSymbolRefExpr(UExpr->getSubExpr());
1775
1776 return 0;
1777}
1778
Jack Carter9e65aa32013-03-22 00:05:30 +00001779bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001780 MCStreamer &Out,
1781 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001782 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001783 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001784 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001785
Jack Carter9e65aa32013-03-22 00:05:30 +00001786 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001787
1788 if (MCID.isBranch() || MCID.isCall()) {
1789 const unsigned Opcode = Inst.getOpcode();
1790 MCOperand Offset;
1791
1792 switch (Opcode) {
1793 default:
1794 break;
Kai Nackee0245392015-01-27 19:11:28 +00001795 case Mips::BBIT0:
1796 case Mips::BBIT032:
1797 case Mips::BBIT1:
1798 case Mips::BBIT132:
1799 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001800 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001801
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001802 case Mips::BEQ:
1803 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804 case Mips::BEQ_MM:
1805 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001806 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001807 Offset = Inst.getOperand(2);
1808 if (!Offset.isImm())
1809 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001810 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001811 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001812 if (OffsetToAlignment(Offset.getImm(),
1813 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001814 return Error(IDLoc, "branch to misaligned address");
1815 break;
1816 case Mips::BGEZ:
1817 case Mips::BGTZ:
1818 case Mips::BLEZ:
1819 case Mips::BLTZ:
1820 case Mips::BGEZAL:
1821 case Mips::BLTZAL:
1822 case Mips::BC1F:
1823 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001824 case Mips::BGEZ_MM:
1825 case Mips::BGTZ_MM:
1826 case Mips::BLEZ_MM:
1827 case Mips::BLTZ_MM:
1828 case Mips::BGEZAL_MM:
1829 case Mips::BLTZAL_MM:
1830 case Mips::BC1F_MM:
1831 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001832 case Mips::BC1EQZC_MMR6:
1833 case Mips::BC1NEZC_MMR6:
1834 case Mips::BC2EQZC_MMR6:
1835 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001836 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001837 Offset = Inst.getOperand(1);
1838 if (!Offset.isImm())
1839 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001840 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001841 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001842 if (OffsetToAlignment(Offset.getImm(),
1843 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001844 return Error(IDLoc, "branch to misaligned address");
1845 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001846 case Mips::BGEC: case Mips::BGEC_MMR6:
1847 case Mips::BLTC: case Mips::BLTC_MMR6:
1848 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1849 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1850 case Mips::BEQC: case Mips::BEQC_MMR6:
1851 case Mips::BNEC: case Mips::BNEC_MMR6:
1852 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1853 Offset = Inst.getOperand(2);
1854 if (!Offset.isImm())
1855 break; // We'll deal with this situation later on when applying fixups.
1856 if (!isIntN(18, Offset.getImm()))
1857 return Error(IDLoc, "branch target out of range");
1858 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1859 return Error(IDLoc, "branch to misaligned address");
1860 break;
1861 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1862 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1863 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1864 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1865 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1866 Offset = Inst.getOperand(1);
1867 if (!Offset.isImm())
1868 break; // We'll deal with this situation later on when applying fixups.
1869 if (!isIntN(18, Offset.getImm()))
1870 return Error(IDLoc, "branch target out of range");
1871 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1872 return Error(IDLoc, "branch to misaligned address");
1873 break;
1874 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1875 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1876 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1877 Offset = Inst.getOperand(1);
1878 if (!Offset.isImm())
1879 break; // We'll deal with this situation later on when applying fixups.
1880 if (!isIntN(23, Offset.getImm()))
1881 return Error(IDLoc, "branch target out of range");
1882 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1883 return Error(IDLoc, "branch to misaligned address");
1884 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001885 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001886 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001887 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001888 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001889 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1890 Offset = Inst.getOperand(1);
1891 if (!Offset.isImm())
1892 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001893 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001894 return Error(IDLoc, "branch target out of range");
1895 if (OffsetToAlignment(Offset.getImm(), 2LL))
1896 return Error(IDLoc, "branch to misaligned address");
1897 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001898 }
1899 }
1900
Daniel Sandersa84989a2014-06-16 13:25:35 +00001901 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1902 // We still accept it but it is a normal nop.
1903 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1904 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1905 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1906 "nop instruction");
1907 }
1908
Kai Nackee0245392015-01-27 19:11:28 +00001909 if (hasCnMips()) {
1910 const unsigned Opcode = Inst.getOpcode();
1911 MCOperand Opnd;
1912 int Imm;
1913
1914 switch (Opcode) {
1915 default:
1916 break;
1917
1918 case Mips::BBIT0:
1919 case Mips::BBIT032:
1920 case Mips::BBIT1:
1921 case Mips::BBIT132:
1922 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1923 // The offset is handled above
1924 Opnd = Inst.getOperand(1);
1925 if (!Opnd.isImm())
1926 return Error(IDLoc, "expected immediate operand kind");
1927 Imm = Opnd.getImm();
1928 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1929 Opcode == Mips::BBIT1 ? 63 : 31))
1930 return Error(IDLoc, "immediate operand value out of range");
1931 if (Imm > 31) {
1932 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1933 : Mips::BBIT132);
1934 Inst.getOperand(1).setImm(Imm - 32);
1935 }
1936 break;
1937
Kai Nackee0245392015-01-27 19:11:28 +00001938 case Mips::SEQi:
1939 case Mips::SNEi:
1940 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1941 Opnd = Inst.getOperand(2);
1942 if (!Opnd.isImm())
1943 return Error(IDLoc, "expected immediate operand kind");
1944 Imm = Opnd.getImm();
1945 if (!isInt<10>(Imm))
1946 return Error(IDLoc, "immediate operand value out of range");
1947 break;
1948 }
1949 }
1950
Simon Dardis509da1a2017-02-13 16:06:48 +00001951 // Warn on division by zero. We're checking here as all instructions get
1952 // processed here, not just the macros that need expansion.
1953 //
1954 // The MIPS backend models most of the divison instructions and macros as
1955 // three operand instructions. The pre-R6 divide instructions however have
1956 // two operands and explicitly define HI/LO as part of the instruction,
1957 // not in the operands.
1958 unsigned FirstOp = 1;
1959 unsigned SecondOp = 2;
1960 switch (Inst.getOpcode()) {
1961 default:
1962 break;
1963 case Mips::SDivIMacro:
1964 case Mips::UDivIMacro:
1965 case Mips::DSDivIMacro:
1966 case Mips::DUDivIMacro:
1967 if (Inst.getOperand(2).getImm() == 0) {
1968 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1969 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1970 Warning(IDLoc, "dividing zero by zero");
1971 else
1972 Warning(IDLoc, "division by zero");
1973 }
1974 break;
1975 case Mips::DSDIV:
1976 case Mips::SDIV:
1977 case Mips::UDIV:
1978 case Mips::DUDIV:
1979 case Mips::UDIV_MM:
1980 case Mips::SDIV_MM:
1981 FirstOp = 0;
1982 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001983 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001984 case Mips::SDivMacro:
1985 case Mips::DSDivMacro:
1986 case Mips::UDivMacro:
1987 case Mips::DUDivMacro:
1988 case Mips::DIV:
1989 case Mips::DIVU:
1990 case Mips::DDIV:
1991 case Mips::DDIVU:
1992 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001993 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001994 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1995 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1996 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1997 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1998 Warning(IDLoc, "dividing zero by zero");
1999 else
2000 Warning(IDLoc, "division by zero");
2001 }
2002 break;
2003 }
2004
Simon Atanasyan50485142016-12-12 17:40:26 +00002005 // For PIC code convert unconditional jump to unconditional branch.
2006 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2007 inPicMode()) {
2008 MCInst BInst;
2009 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2010 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2011 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2012 BInst.addOperand(Inst.getOperand(0));
2013 Inst = BInst;
2014 }
2015
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002016 // This expansion is not in a function called by tryExpandInstruction()
2017 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002018 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2019 inPicMode()) {
2020 warnIfNoMacro(IDLoc);
2021
2022 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2023
2024 // We can do this expansion if there's only 1 symbol in the argument
2025 // expression.
2026 if (countMCSymbolRefExpr(JalExpr) > 1)
2027 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2028
2029 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002030 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002031 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2032
2033 // FIXME: Add support for label+offset operands (currently causes an error).
2034 // FIXME: Add support for forward-declared local symbols.
2035 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002036 if (JalSym->isInSection() || JalSym->isTemporary() ||
2037 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002038 if (isABI_O32()) {
2039 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002040 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002041 // R_(MICRO)MIPS_GOT16 label
2042 // addiu $25, $25, 0
2043 // R_(MICRO)MIPS_LO16 label
2044 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002045 const MCExpr *Got16RelocExpr =
2046 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2047 const MCExpr *Lo16RelocExpr =
2048 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002049
Daniel Sandersa736b372016-04-29 13:33:12 +00002050 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2051 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2052 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2053 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002054 } else if (isABI_N32() || isABI_N64()) {
2055 // If it's a local symbol and the N32/N64 ABIs are being used,
2056 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002057 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002058 // R_(MICRO)MIPS_GOT_DISP label
2059 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002060 const MCExpr *GotDispRelocExpr =
2061 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002062
Daniel Sandersa736b372016-04-29 13:33:12 +00002063 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2064 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2065 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002066 }
2067 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002068 // If it's an external/weak symbol, we expand to:
2069 // lw/ld $25, 0($gp)
2070 // R_(MICRO)MIPS_CALL16 label
2071 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002072 const MCExpr *Call16RelocExpr =
2073 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002074
Daniel Sandersa736b372016-04-29 13:33:12 +00002075 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2076 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002077 }
2078
2079 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002080 if (IsCpRestoreSet && inMicroMipsMode())
2081 JalrInst.setOpcode(Mips::JALRS_MM);
2082 else
2083 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002084 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2085 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2086
2087 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2088 // This relocation is supposed to be an optimization hint for the linker
2089 // and is not necessary for correctness.
2090
2091 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002092 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002093 }
2094
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002095 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2096 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002097 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002098 // reference or immediate we may have to expand instructions.
2099 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002100 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002101 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2102 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002103 MCOperand &Op = Inst.getOperand(i);
2104 if (Op.isImm()) {
2105 int MemOffset = Op.getImm();
2106 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002108 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002109 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002110 }
2111 } else if (Op.isExpr()) {
2112 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002114 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002115 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002116 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002117 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002118 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002119 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002120 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002121 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002122 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002123 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002124 }
2125 }
2126 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002127 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002128 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002129
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002130 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002131 if (MCID.mayLoad()) {
2132 // Try to create 16-bit GP relative load instruction.
2133 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2134 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2135 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2136 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2137 MCOperand &Op = Inst.getOperand(i);
2138 if (Op.isImm()) {
2139 int MemOffset = Op.getImm();
2140 MCOperand &DstReg = Inst.getOperand(0);
2141 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002142 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002143 getContext().getRegisterInfo()->getRegClass(
2144 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002145 (BaseReg.getReg() == Mips::GP ||
2146 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002147
Daniel Sandersa736b372016-04-29 13:33:12 +00002148 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2149 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002150 return false;
2151 }
2152 }
2153 }
2154 } // for
2155 } // if load
2156
2157 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2158
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002159 MCOperand Opnd;
2160 int Imm;
2161
2162 switch (Inst.getOpcode()) {
2163 default:
2164 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002165 case Mips::ADDIUSP_MM:
2166 Opnd = Inst.getOperand(0);
2167 if (!Opnd.isImm())
2168 return Error(IDLoc, "expected immediate operand kind");
2169 Imm = Opnd.getImm();
2170 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2171 Imm % 4 != 0)
2172 return Error(IDLoc, "immediate operand value out of range");
2173 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002174 case Mips::SLL16_MM:
2175 case Mips::SRL16_MM:
2176 Opnd = Inst.getOperand(2);
2177 if (!Opnd.isImm())
2178 return Error(IDLoc, "expected immediate operand kind");
2179 Imm = Opnd.getImm();
2180 if (Imm < 1 || Imm > 8)
2181 return Error(IDLoc, "immediate operand value out of range");
2182 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002183 case Mips::LI16_MM:
2184 Opnd = Inst.getOperand(1);
2185 if (!Opnd.isImm())
2186 return Error(IDLoc, "expected immediate operand kind");
2187 Imm = Opnd.getImm();
2188 if (Imm < -1 || Imm > 126)
2189 return Error(IDLoc, "immediate operand value out of range");
2190 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002191 case Mips::ADDIUR2_MM:
2192 Opnd = Inst.getOperand(2);
2193 if (!Opnd.isImm())
2194 return Error(IDLoc, "expected immediate operand kind");
2195 Imm = Opnd.getImm();
2196 if (!(Imm == 1 || Imm == -1 ||
2197 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2198 return Error(IDLoc, "immediate operand value out of range");
2199 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002200 case Mips::ANDI16_MM:
2201 Opnd = Inst.getOperand(2);
2202 if (!Opnd.isImm())
2203 return Error(IDLoc, "expected immediate operand kind");
2204 Imm = Opnd.getImm();
2205 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2206 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2207 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2208 return Error(IDLoc, "immediate operand value out of range");
2209 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002210 case Mips::LBU16_MM:
2211 Opnd = Inst.getOperand(2);
2212 if (!Opnd.isImm())
2213 return Error(IDLoc, "expected immediate operand kind");
2214 Imm = Opnd.getImm();
2215 if (Imm < -1 || Imm > 14)
2216 return Error(IDLoc, "immediate operand value out of range");
2217 break;
2218 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002219 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002220 Opnd = Inst.getOperand(2);
2221 if (!Opnd.isImm())
2222 return Error(IDLoc, "expected immediate operand kind");
2223 Imm = Opnd.getImm();
2224 if (Imm < 0 || Imm > 15)
2225 return Error(IDLoc, "immediate operand value out of range");
2226 break;
2227 case Mips::LHU16_MM:
2228 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002229 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002230 Opnd = Inst.getOperand(2);
2231 if (!Opnd.isImm())
2232 return Error(IDLoc, "expected immediate operand kind");
2233 Imm = Opnd.getImm();
2234 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2235 return Error(IDLoc, "immediate operand value out of range");
2236 break;
2237 case Mips::LW16_MM:
2238 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002239 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002240 Opnd = Inst.getOperand(2);
2241 if (!Opnd.isImm())
2242 return Error(IDLoc, "expected immediate operand kind");
2243 Imm = Opnd.getImm();
2244 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2245 return Error(IDLoc, "immediate operand value out of range");
2246 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002247 case Mips::ADDIUPC_MM:
2248 MCOperand Opnd = Inst.getOperand(1);
2249 if (!Opnd.isImm())
2250 return Error(IDLoc, "expected immediate operand kind");
2251 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002252 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002253 return Error(IDLoc, "immediate operand value out of range");
2254 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002255 }
2256 }
2257
Daniel Sandersd8c07762016-04-18 12:35:36 +00002258 bool FillDelaySlot =
2259 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2260 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002261 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002262
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002263 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002264 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002265 switch (ExpandResult) {
2266 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002267 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002268 break;
2269 case MER_Success:
2270 break;
2271 case MER_Fail:
2272 return true;
2273 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002274
Daniel Sanderscda908a2016-05-16 09:10:13 +00002275 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2276 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002277 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002278 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002279 TOut.updateABIInfo(*this);
2280 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002281
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002282 // If this instruction has a delay slot and .set reorder is active,
2283 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002284 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002285 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2286 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002287 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002288
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002289 if ((Inst.getOpcode() == Mips::JalOneReg ||
2290 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2291 isPicAndNotNxxAbi()) {
2292 if (IsCpRestoreSet) {
2293 // We need a NOP between the JALR and the LW:
2294 // If .set reorder has been used, we've already emitted a NOP.
2295 // If .set noreorder has been used, we need to emit a NOP at this point.
2296 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002297 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2298 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002299
2300 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002301 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002302 } else
2303 Warning(IDLoc, "no .cprestore used in PIC mode");
2304 }
2305
Jack Carter9e65aa32013-03-22 00:05:30 +00002306 return false;
2307}
2308
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002309MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002310MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2311 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002312 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002313 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002314 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002315 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002316 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002317 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002318 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002319 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002320 case Mips::LoadAddrImm64:
2321 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2322 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2323 "expected immediate operand kind");
2324
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002325 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2326 Inst.getOperand(1),
2327 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002328 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002329 ? MER_Fail
2330 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002331 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002332 case Mips::LoadAddrReg64:
2333 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2334 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2335 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2336 "expected immediate operand kind");
2337
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002338 return expandLoadAddress(Inst.getOperand(0).getReg(),
2339 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2340 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002341 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002342 ? MER_Fail
2343 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002344 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002345 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002346 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2347 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002348 case Mips::SWM_MM:
2349 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002350 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2351 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002352 case Mips::JalOneReg:
2353 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002354 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002355 case Mips::BneImm:
2356 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002357 case Mips::BEQLImmMacro:
2358 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002359 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002360 case Mips::BLT:
2361 case Mips::BLE:
2362 case Mips::BGE:
2363 case Mips::BGT:
2364 case Mips::BLTU:
2365 case Mips::BLEU:
2366 case Mips::BGEU:
2367 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002368 case Mips::BLTL:
2369 case Mips::BLEL:
2370 case Mips::BGEL:
2371 case Mips::BGTL:
2372 case Mips::BLTUL:
2373 case Mips::BLEUL:
2374 case Mips::BGEUL:
2375 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002376 case Mips::BLTImmMacro:
2377 case Mips::BLEImmMacro:
2378 case Mips::BGEImmMacro:
2379 case Mips::BGTImmMacro:
2380 case Mips::BLTUImmMacro:
2381 case Mips::BLEUImmMacro:
2382 case Mips::BGEUImmMacro:
2383 case Mips::BGTUImmMacro:
2384 case Mips::BLTLImmMacro:
2385 case Mips::BLELImmMacro:
2386 case Mips::BGELImmMacro:
2387 case Mips::BGTLImmMacro:
2388 case Mips::BLTULImmMacro:
2389 case Mips::BLEULImmMacro:
2390 case Mips::BGEULImmMacro:
2391 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002392 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002393 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002394 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002395 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2396 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002397 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002398 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002399 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2400 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002401 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002402 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002403 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2404 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002405 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002406 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002407 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2408 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002409 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002410 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2411 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002412 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002413 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002414 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002415 case Mips::PseudoTRUNC_W_D:
2416 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2417 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002418
2419 case Mips::LoadImmSingleGPR:
2420 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2421 ? MER_Fail
2422 : MER_Success;
2423 case Mips::LoadImmSingleFGR:
2424 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2425 ? MER_Fail
2426 : MER_Success;
2427 case Mips::LoadImmDoubleGPR:
2428 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2429 ? MER_Fail
2430 : MER_Success;
2431 case Mips::LoadImmDoubleFGR:
2432 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2433 ? MER_Fail
2434 : MER_Success;
2435 case Mips::LoadImmDoubleFGR_32:
2436 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2437 ? MER_Fail
2438 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002439 case Mips::Ulh:
2440 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2441 case Mips::Ulhu:
2442 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002443 case Mips::Ush:
2444 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002445 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002446 case Mips::Usw:
2447 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002448 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002449 case Mips::NORImm64:
2450 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2451 case Mips::SLTImm64:
2452 if (isInt<16>(Inst.getOperand(2).getImm())) {
2453 Inst.setOpcode(Mips::SLTi64);
2454 return MER_NotAMacro;
2455 }
2456 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2457 case Mips::SLTUImm64:
2458 if (isInt<16>(Inst.getOperand(2).getImm())) {
2459 Inst.setOpcode(Mips::SLTiu64);
2460 return MER_NotAMacro;
2461 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002462 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002463 case Mips::ADDi: case Mips::ADDi_MM:
2464 case Mips::ADDiu: case Mips::ADDiu_MM:
2465 case Mips::SLTi: case Mips::SLTi_MM:
2466 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002467 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2468 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2469 int64_t ImmValue = Inst.getOperand(2).getImm();
2470 if (isInt<16>(ImmValue))
2471 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002472 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2473 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002474 }
2475 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002476 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2477 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2478 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002479 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2480 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2481 int64_t ImmValue = Inst.getOperand(2).getImm();
2482 if (isUInt<16>(ImmValue))
2483 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002484 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2485 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002486 }
2487 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002488 case Mips::ROL:
2489 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002490 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002491 case Mips::ROLImm:
2492 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002493 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002494 case Mips::DROL:
2495 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002496 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002497 case Mips::DROLImm:
2498 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002499 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002500 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002501 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002502 case Mips::MULImmMacro:
2503 case Mips::DMULImmMacro:
2504 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2505 case Mips::MULOMacro:
2506 case Mips::DMULOMacro:
2507 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2508 case Mips::MULOUMacro:
2509 case Mips::DMULOUMacro:
2510 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2511 case Mips::DMULMacro:
2512 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002513 case Mips::LDMacro:
2514 case Mips::SDMacro:
2515 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2516 Inst.getOpcode() == Mips::LDMacro)
2517 ? MER_Fail
2518 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002519 case Mips::SEQMacro:
2520 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2521 case Mips::SEQIMacro:
2522 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002523 case Mips::MFTC0: case Mips::MTTC0:
2524 case Mips::MFTGPR: case Mips::MTTGPR:
2525 case Mips::MFTLO: case Mips::MTTLO:
2526 case Mips::MFTHI: case Mips::MTTHI:
2527 case Mips::MFTACX: case Mips::MTTACX:
2528 case Mips::MFTDSP: case Mips::MTTDSP:
2529 case Mips::MFTC1: case Mips::MTTC1:
2530 case Mips::MFTHC1: case Mips::MTTHC1:
2531 case Mips::CFTC1: case Mips::CTTC1:
2532 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 }
Jack Carter30a59822012-10-04 04:03:53 +00002534}
Jack Carter92995f12012-10-06 00:53:28 +00002535
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002536bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002537 MCStreamer &Out,
2538 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002539 MipsTargetStreamer &TOut = getTargetStreamer();
2540
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002541 // Create a JALR instruction which is going to replace the pseudo-JAL.
2542 MCInst JalrInst;
2543 JalrInst.setLoc(IDLoc);
2544 const MCOperand FirstRegOp = Inst.getOperand(0);
2545 const unsigned Opcode = Inst.getOpcode();
2546
2547 if (Opcode == Mips::JalOneReg) {
2548 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002549 if (IsCpRestoreSet && inMicroMipsMode()) {
2550 JalrInst.setOpcode(Mips::JALRS16_MM);
2551 JalrInst.addOperand(FirstRegOp);
2552 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002553 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002554 JalrInst.addOperand(FirstRegOp);
2555 } else {
2556 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002557 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002558 JalrInst.addOperand(FirstRegOp);
2559 }
2560 } else if (Opcode == Mips::JalTwoReg) {
2561 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002562 if (IsCpRestoreSet && inMicroMipsMode())
2563 JalrInst.setOpcode(Mips::JALRS_MM);
2564 else
2565 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002566 JalrInst.addOperand(FirstRegOp);
2567 const MCOperand SecondRegOp = Inst.getOperand(1);
2568 JalrInst.addOperand(SecondRegOp);
2569 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002570 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002571
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002572 // If .set reorder is active and branch instruction has a delay slot,
2573 // emit a NOP after it.
2574 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002575 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2576 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2577 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002578
2579 return false;
2580}
2581
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002582/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002583template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002584 unsigned BitNum = findFirstSet(x);
2585
2586 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2587}
2588
2589/// Load (or add) an immediate into a register.
2590///
2591/// @param ImmValue The immediate to load.
2592/// @param DstReg The register that will hold the immediate.
2593/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2594/// for a simple initialization.
2595/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2596/// @param IsAddress True if the immediate represents an address. False if it
2597/// is an integer.
2598/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002599bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002600 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002601 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2602 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002603 MipsTargetStreamer &TOut = getTargetStreamer();
2604
Toma Tabacu00e98672015-05-01 12:19:27 +00002605 if (!Is32BitImm && !isGP64bit()) {
2606 Error(IDLoc, "instruction requires a 64-bit architecture");
2607 return true;
2608 }
2609
Daniel Sanders03f9c012015-07-14 12:24:22 +00002610 if (Is32BitImm) {
2611 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2612 // Sign extend up to 64-bit so that the predicates match the hardware
2613 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2614 // true.
2615 ImmValue = SignExtend64<32>(ImmValue);
2616 } else {
2617 Error(IDLoc, "instruction requires a 32-bit immediate");
2618 return true;
2619 }
2620 }
2621
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002622 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2623 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2624
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002625 bool UseSrcReg = false;
2626 if (SrcReg != Mips::NoRegister)
2627 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002628
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002629 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002630 if (UseSrcReg &&
2631 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002632 // At this point we need AT to perform the expansions and we exit if it is
2633 // not available.
2634 unsigned ATReg = getATReg(IDLoc);
2635 if (!ATReg)
2636 return true;
2637 TmpReg = ATReg;
2638 }
2639
Daniel Sanders03f9c012015-07-14 12:24:22 +00002640 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002641 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002642 SrcReg = ZeroReg;
2643
2644 // This doesn't quite follow the usual ABI expectations for N32 but matches
2645 // traditional assembler behaviour. N32 would normally use addiu for both
2646 // integers and addresses.
2647 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002648 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002649 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002650 }
2651
Daniel Sandersa736b372016-04-29 13:33:12 +00002652 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002653 return false;
2654 }
2655
2656 if (isUInt<16>(ImmValue)) {
2657 unsigned TmpReg = DstReg;
2658 if (SrcReg == DstReg) {
2659 TmpReg = getATReg(IDLoc);
2660 if (!TmpReg)
2661 return true;
2662 }
2663
Daniel Sandersa736b372016-04-29 13:33:12 +00002664 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002665 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002666 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002667 return false;
2668 }
2669
2670 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002671 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002672
Toma Tabacu79588102015-04-29 10:19:56 +00002673 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2674 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002675 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002676 // Traditional behaviour seems to special case this particular value. It's
2677 // not clear why other masks are handled differently.
2678 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002679 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2680 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002681 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002682 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002683 return false;
2684 }
2685
2686 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002687 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002688 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2689 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002690 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002691 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002692 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002693 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002694 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002695 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002696
Daniel Sandersa736b372016-04-29 13:33:12 +00002697 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002698 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002699 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002700 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002701 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002702 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002703 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002704
2705 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2706 if (Is32BitImm) {
2707 Error(IDLoc, "instruction requires a 32-bit immediate");
2708 return true;
2709 }
2710
2711 // Traditionally, these immediates are shifted as little as possible and as
2712 // such we align the most significant bit to bit 15 of our temporary.
2713 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2714 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2715 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2716 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002717 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2718 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002719
2720 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002721 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002722
2723 return false;
2724 }
2725
2726 warnIfNoMacro(IDLoc);
2727
2728 // The remaining case is packed with a sequence of dsll and ori with zeros
2729 // being omitted and any neighbouring dsll's being coalesced.
2730 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2731
2732 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2733 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002734 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002735 return false;
2736
2737 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2738 // skip it and defer the shift to the next chunk.
2739 unsigned ShiftCarriedForwards = 16;
2740 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2741 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2742
2743 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002744 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2745 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002746 ShiftCarriedForwards = 0;
2747 }
2748
2749 ShiftCarriedForwards += 16;
2750 }
2751 ShiftCarriedForwards -= 16;
2752
2753 // Finish any remaining shifts left by trailing zeros.
2754 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002755 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002756
2757 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002758 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002759
Matheus Almeida3813d572014-06-19 14:39:14 +00002760 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002761}
Jack Carter92995f12012-10-06 00:53:28 +00002762
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002763bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002764 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002765 const MCOperand &ImmOp = Inst.getOperand(1);
2766 assert(ImmOp.isImm() && "expected immediate operand kind");
2767 const MCOperand &DstRegOp = Inst.getOperand(0);
2768 assert(DstRegOp.isReg() && "expected register operand kind");
2769
2770 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002771 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002772 return true;
2773
2774 return false;
2775}
2776
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002777bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2778 const MCOperand &Offset,
2779 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002780 MCStreamer &Out,
2781 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002782 // la can't produce a usable address when addresses are 64-bit.
2783 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2784 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2785 // We currently can't do this because we depend on the equality
2786 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2787 Error(IDLoc, "la used to load 64-bit address");
2788 // Continue as if we had 'dla' instead.
2789 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002790 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002791 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002792
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002793 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002794 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002795 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002796 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002797 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002798
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002799 if (!Offset.isImm())
2800 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002801 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002802
Scott Egerton24557012016-01-21 15:11:01 +00002803 if (!ABI.ArePtrs64bit()) {
2804 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2805 Is32BitAddress = true;
2806 }
2807
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002808 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002809 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002810}
2811
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002812bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2813 unsigned DstReg, unsigned SrcReg,
2814 bool Is32BitSym, SMLoc IDLoc,
2815 MCStreamer &Out,
2816 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002817 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002818 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002819 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002820 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002821
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002822 if (inPicMode() && ABI.IsO32()) {
2823 MCValue Res;
2824 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2825 Error(IDLoc, "expected relocatable expression");
2826 return true;
2827 }
2828 if (Res.getSymB() != nullptr) {
2829 Error(IDLoc, "expected relocatable expression with only one symbol");
2830 return true;
2831 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002832
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002833 // The case where the result register is $25 is somewhat special. If the
2834 // symbol in the final relocation is external and not modified with a
2835 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2836 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002837 Res.getConstant() == 0 &&
2838 !(Res.getSymA()->getSymbol().isInSection() ||
2839 Res.getSymA()->getSymbol().isTemporary() ||
2840 (Res.getSymA()->getSymbol().isELF() &&
2841 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2842 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002843 const MCExpr *CallExpr =
2844 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2845 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2846 MCOperand::createExpr(CallExpr), IDLoc, STI);
2847 return false;
2848 }
2849
2850 // The remaining cases are:
2851 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2852 // >addiu $tmp, $tmp, %lo(offset)
2853 // >addiu $rd, $tmp, $rs
2854 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2855 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2856 // >addiu $rd, $tmp, $rs
2857 // The addiu's marked with a '>' may be omitted if they are redundant. If
2858 // this happens then the last instruction must use $rd as the result
2859 // register.
2860 const MipsMCExpr *GotExpr =
2861 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2862 const MCExpr *LoExpr = nullptr;
2863 if (Res.getSymA()->getSymbol().isInSection() ||
2864 Res.getSymA()->getSymbol().isTemporary())
2865 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2866 else if (Res.getConstant() != 0) {
2867 // External symbols fully resolve the symbol with just the %got(symbol)
2868 // but we must still account for any offset to the symbol for expressions
2869 // like symbol+8.
2870 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2871 }
2872
2873 unsigned TmpReg = DstReg;
2874 if (UseSrcReg &&
2875 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2876 SrcReg)) {
2877 // If $rs is the same as $rd, we need to use AT.
2878 // If it is not available we exit.
2879 unsigned ATReg = getATReg(IDLoc);
2880 if (!ATReg)
2881 return true;
2882 TmpReg = ATReg;
2883 }
2884
2885 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2886 MCOperand::createExpr(GotExpr), IDLoc, STI);
2887
2888 if (LoExpr)
2889 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2890 IDLoc, STI);
2891
2892 if (UseSrcReg)
2893 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2894
2895 return false;
2896 }
2897
Simon Dardisda96c432017-06-30 15:44:27 +00002898 if (inPicMode() && ABI.ArePtrs64bit()) {
2899 MCValue Res;
2900 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2901 Error(IDLoc, "expected relocatable expression");
2902 return true;
2903 }
2904 if (Res.getSymB() != nullptr) {
2905 Error(IDLoc, "expected relocatable expression with only one symbol");
2906 return true;
2907 }
2908
2909 // The case where the result register is $25 is somewhat special. If the
2910 // symbol in the final relocation is external and not modified with a
2911 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2912 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2913 Res.getConstant() == 0 &&
2914 !(Res.getSymA()->getSymbol().isInSection() ||
2915 Res.getSymA()->getSymbol().isTemporary() ||
2916 (Res.getSymA()->getSymbol().isELF() &&
2917 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2918 ELF::STB_LOCAL))) {
2919 const MCExpr *CallExpr =
2920 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2921 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2922 MCOperand::createExpr(CallExpr), IDLoc, STI);
2923 return false;
2924 }
2925
2926 // The remaining cases are:
2927 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2928 // >daddiu $tmp, $tmp, offset
2929 // >daddu $rd, $tmp, $rs
2930 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2931 // this happens then the last instruction must use $rd as the result
2932 // register.
2933 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2934 Res.getSymA(),
2935 getContext());
2936 const MCExpr *LoExpr = nullptr;
2937 if (Res.getConstant() != 0) {
2938 // Symbols fully resolve with just the %got_disp(symbol) but we
2939 // must still account for any offset to the symbol for
2940 // expressions like symbol+8.
2941 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2942
2943 // FIXME: Offsets greater than 16 bits are not yet implemented.
2944 // FIXME: The correct range is a 32-bit sign-extended number.
2945 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2946 Error(IDLoc, "macro instruction uses large offset, which is not "
2947 "currently supported");
2948 return true;
2949 }
2950 }
2951
2952 unsigned TmpReg = DstReg;
2953 if (UseSrcReg &&
2954 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2955 SrcReg)) {
2956 // If $rs is the same as $rd, we need to use AT.
2957 // If it is not available we exit.
2958 unsigned ATReg = getATReg(IDLoc);
2959 if (!ATReg)
2960 return true;
2961 TmpReg = ATReg;
2962 }
2963
2964 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2965 MCOperand::createExpr(GotExpr), IDLoc, STI);
2966
2967 if (LoExpr)
2968 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2969 IDLoc, STI);
2970
2971 if (UseSrcReg)
2972 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2973
2974 return false;
2975 }
2976
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002977 const MipsMCExpr *HiExpr =
2978 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2979 const MipsMCExpr *LoExpr =
2980 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002981
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002982 // This is the 64-bit symbol address expansion.
2983 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002984 // We need AT for the 64-bit expansion in the cases where the optional
2985 // source register is the destination register and for the superscalar
2986 // scheduled form.
2987 //
2988 // If it is not available we exit if the destination is the same as the
2989 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002990
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002991 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002992 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002993 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002994 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002995
Simon Dardis3aa8a902017-02-06 12:43:46 +00002996 bool RdRegIsRsReg =
2997 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2998
2999 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3000 unsigned ATReg = getATReg(IDLoc);
3001
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003002 // If $rs is the same as $rd:
3003 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3004 // daddiu $at, $at, %higher(sym)
3005 // dsll $at, $at, 16
3006 // daddiu $at, $at, %hi(sym)
3007 // dsll $at, $at, 16
3008 // daddiu $at, $at, %lo(sym)
3009 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003010 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3011 STI);
3012 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3013 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3014 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3015 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3016 IDLoc, STI);
3017 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3018 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3019 IDLoc, STI);
3020 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003021
3022 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003023 } else if (canUseATReg() && !RdRegIsRsReg) {
3024 unsigned ATReg = getATReg(IDLoc);
3025
3026 // If the $rs is different from $rd or if $rs isn't specified and we
3027 // have $at available:
3028 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3029 // lui $at, %hi(sym)
3030 // daddiu $rd, $rd, %higher(sym)
3031 // daddiu $at, $at, %lo(sym)
3032 // dsll32 $rd, $rd, 0
3033 // daddu $rd, $rd, $at
3034 // (daddu $rd, $rd, $rs)
3035 //
3036 // Which is preferred for superscalar issue.
3037 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3038 STI);
3039 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3040 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3041 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3042 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3043 IDLoc, STI);
3044 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3045 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3046 if (UseSrcReg)
3047 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3048
3049 return false;
3050 } else if (!canUseATReg() && !RdRegIsRsReg) {
3051 // Otherwise, synthesize the address in the destination register
3052 // serially:
3053 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3054 // daddiu $rd, $rd, %higher(sym)
3055 // dsll $rd, $rd, 16
3056 // daddiu $rd, $rd, %hi(sym)
3057 // dsll $rd, $rd, 16
3058 // daddiu $rd, $rd, %lo(sym)
3059 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3060 STI);
3061 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3062 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3063 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3064 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3065 MCOperand::createExpr(HiExpr), IDLoc, STI);
3066 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3067 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3068 MCOperand::createExpr(LoExpr), IDLoc, STI);
3069 if (UseSrcReg)
3070 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3071
3072 return false;
3073 } else {
3074 // We have a case where SrcReg == DstReg and we don't have $at
3075 // available. We can't expand this case, so error out appropriately.
3076 assert(SrcReg == DstReg && !canUseATReg() &&
3077 "Could have expanded dla but didn't?");
3078 reportParseError(IDLoc,
3079 "pseudo-instruction requires $at, which is not available");
3080 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003081 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003082 }
3083
3084 // And now, the 32-bit symbol address expansion:
3085 // If $rs is the same as $rd:
3086 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3087 // ori $at, $at, %lo(sym)
3088 // addu $rd, $at, $rd
3089 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3090 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3091 // ori $rd, $rd, %lo(sym)
3092 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003093 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003094 if (UseSrcReg &&
3095 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003096 // If $rs is the same as $rd, we need to use AT.
3097 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003098 unsigned ATReg = getATReg(IDLoc);
3099 if (!ATReg)
3100 return true;
3101 TmpReg = ATReg;
3102 }
3103
Daniel Sandersa736b372016-04-29 13:33:12 +00003104 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3105 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3106 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003107
Toma Tabacufb9d1252015-06-22 12:08:39 +00003108 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003109 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003110 else
Scott Egerton24557012016-01-21 15:11:01 +00003111 assert(
3112 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003113
Toma Tabacu674825c2015-06-16 12:16:24 +00003114 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003115}
3116
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003117// Each double-precision register DO-D15 overlaps with two of the single
3118// precision registers F0-F31. As an example, all of the following hold true:
3119// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3120static unsigned nextReg(unsigned Reg) {
3121 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3122 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3123 switch (Reg) {
3124 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3125 case Mips::ZERO: return Mips::AT;
3126 case Mips::AT: return Mips::V0;
3127 case Mips::V0: return Mips::V1;
3128 case Mips::V1: return Mips::A0;
3129 case Mips::A0: return Mips::A1;
3130 case Mips::A1: return Mips::A2;
3131 case Mips::A2: return Mips::A3;
3132 case Mips::A3: return Mips::T0;
3133 case Mips::T0: return Mips::T1;
3134 case Mips::T1: return Mips::T2;
3135 case Mips::T2: return Mips::T3;
3136 case Mips::T3: return Mips::T4;
3137 case Mips::T4: return Mips::T5;
3138 case Mips::T5: return Mips::T6;
3139 case Mips::T6: return Mips::T7;
3140 case Mips::T7: return Mips::S0;
3141 case Mips::S0: return Mips::S1;
3142 case Mips::S1: return Mips::S2;
3143 case Mips::S2: return Mips::S3;
3144 case Mips::S3: return Mips::S4;
3145 case Mips::S4: return Mips::S5;
3146 case Mips::S5: return Mips::S6;
3147 case Mips::S6: return Mips::S7;
3148 case Mips::S7: return Mips::T8;
3149 case Mips::T8: return Mips::T9;
3150 case Mips::T9: return Mips::K0;
3151 case Mips::K0: return Mips::K1;
3152 case Mips::K1: return Mips::GP;
3153 case Mips::GP: return Mips::SP;
3154 case Mips::SP: return Mips::FP;
3155 case Mips::FP: return Mips::RA;
3156 case Mips::RA: return Mips::ZERO;
3157 case Mips::D0: return Mips::F1;
3158 case Mips::D1: return Mips::F3;
3159 case Mips::D2: return Mips::F5;
3160 case Mips::D3: return Mips::F7;
3161 case Mips::D4: return Mips::F9;
3162 case Mips::D5: return Mips::F11;
3163 case Mips::D6: return Mips::F13;
3164 case Mips::D7: return Mips::F15;
3165 case Mips::D8: return Mips::F17;
3166 case Mips::D9: return Mips::F19;
3167 case Mips::D10: return Mips::F21;
3168 case Mips::D11: return Mips::F23;
3169 case Mips::D12: return Mips::F25;
3170 case Mips::D13: return Mips::F27;
3171 case Mips::D14: return Mips::F29;
3172 case Mips::D15: return Mips::F31;
3173 }
3174}
3175
3176// FIXME: This method is too general. In principle we should compute the number
3177// of instructions required to synthesize the immediate inline compared to
3178// synthesizing the address inline and relying on non .text sections.
3179// For static O32 and N32 this may yield a small benefit, for static N64 this is
3180// likely to yield a much larger benefit as we have to synthesize a 64bit
3181// address to load a 64 bit value.
3182bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3183 MCSymbol *Sym) {
3184 unsigned ATReg = getATReg(IDLoc);
3185 if (!ATReg)
3186 return true;
3187
3188 if(IsPicEnabled) {
3189 const MCExpr *GotSym =
3190 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3191 const MipsMCExpr *GotExpr =
3192 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3193
3194 if(isABI_O32() || isABI_N32()) {
3195 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3196 IDLoc, STI);
3197 } else { //isABI_N64()
3198 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3199 IDLoc, STI);
3200 }
3201 } else { //!IsPicEnabled
3202 const MCExpr *HiSym =
3203 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3204 const MipsMCExpr *HiExpr =
3205 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3206
3207 // FIXME: This is technically correct but gives a different result to gas,
3208 // but gas is incomplete there (it has a fixme noting it doesn't work with
3209 // 64-bit addresses).
3210 // FIXME: With -msym32 option, the address expansion for N64 should probably
3211 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3212 // symbol's value is considered sign extended.
3213 if(isABI_O32() || isABI_N32()) {
3214 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3215 } else { //isABI_N64()
3216 const MCExpr *HighestSym =
3217 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3218 const MipsMCExpr *HighestExpr =
3219 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3220 const MCExpr *HigherSym =
3221 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3222 const MipsMCExpr *HigherExpr =
3223 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3224
3225 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3226 STI);
3227 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3228 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3229 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3230 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3231 IDLoc, STI);
3232 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3233 }
3234 }
3235 return false;
3236}
3237
3238bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3239 bool Is64FPU, SMLoc IDLoc,
3240 MCStreamer &Out,
3241 const MCSubtargetInfo *STI) {
3242 MipsTargetStreamer &TOut = getTargetStreamer();
3243 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3244 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3245 "Invalid instruction operand.");
3246
3247 unsigned FirstReg = Inst.getOperand(0).getReg();
3248 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3249
3250 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3251 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3252 // exponent field), convert it to double (e.g. 1 to 1.0)
3253 if ((HiImmOp64 & 0x7ff00000) == 0) {
3254 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3255 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3256 }
3257
3258 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3259 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3260
3261 if (IsSingle) {
3262 // Conversion of a double in an uint64_t to a float in a uint32_t,
3263 // retaining the bit pattern of a float.
3264 uint32_t ImmOp32;
3265 double doubleImm = BitsToDouble(ImmOp64);
3266 float tmp_float = static_cast<float>(doubleImm);
3267 ImmOp32 = FloatToBits(tmp_float);
3268
3269 if (IsGPR) {
3270 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3271 Out, STI))
3272 return true;
3273 return false;
3274 } else {
3275 unsigned ATReg = getATReg(IDLoc);
3276 if (!ATReg)
3277 return true;
3278 if (LoImmOp64 == 0) {
3279 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3280 Out, STI))
3281 return true;
3282 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3283 return false;
3284 }
3285
3286 MCSection *CS = getStreamer().getCurrentSectionOnly();
3287 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3288 // where appropriate.
3289 MCSection *ReadOnlySection = getContext().getELFSection(
3290 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3291
3292 MCSymbol *Sym = getContext().createTempSymbol();
3293 const MCExpr *LoSym =
3294 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3295 const MipsMCExpr *LoExpr =
3296 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3297
3298 getStreamer().SwitchSection(ReadOnlySection);
3299 getStreamer().EmitLabel(Sym, IDLoc);
3300 getStreamer().EmitIntValue(ImmOp32, 4);
3301 getStreamer().SwitchSection(CS);
3302
3303 if(emitPartialAddress(TOut, IDLoc, Sym))
3304 return true;
3305 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3306 MCOperand::createExpr(LoExpr), IDLoc, STI);
3307 }
3308 return false;
3309 }
3310
3311 // if(!IsSingle)
3312 unsigned ATReg = getATReg(IDLoc);
3313 if (!ATReg)
3314 return true;
3315
3316 if (IsGPR) {
3317 if (LoImmOp64 == 0) {
3318 if(isABI_N32() || isABI_N64()) {
3319 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3320 IDLoc, Out, STI))
3321 return true;
3322 return false;
3323 } else {
3324 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3325 IDLoc, Out, STI))
3326 return true;
3327
3328 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3329 IDLoc, Out, STI))
3330 return true;
3331 return false;
3332 }
3333 }
3334
3335 MCSection *CS = getStreamer().getCurrentSectionOnly();
3336 MCSection *ReadOnlySection = getContext().getELFSection(
3337 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3338
3339 MCSymbol *Sym = getContext().createTempSymbol();
3340 const MCExpr *LoSym =
3341 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3342 const MipsMCExpr *LoExpr =
3343 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3344
3345 getStreamer().SwitchSection(ReadOnlySection);
3346 getStreamer().EmitLabel(Sym, IDLoc);
3347 getStreamer().EmitIntValue(HiImmOp64, 4);
3348 getStreamer().EmitIntValue(LoImmOp64, 4);
3349 getStreamer().SwitchSection(CS);
3350
3351 if(emitPartialAddress(TOut, IDLoc, Sym))
3352 return true;
3353 if(isABI_N64())
3354 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3355 MCOperand::createExpr(LoExpr), IDLoc, STI);
3356 else
3357 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3358 MCOperand::createExpr(LoExpr), IDLoc, STI);
3359
3360 if(isABI_N32() || isABI_N64())
3361 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3362 else {
3363 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3364 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3365 }
3366 return false;
3367 } else { // if(!IsGPR && !IsSingle)
3368 if ((LoImmOp64 == 0) &&
3369 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3370 // FIXME: In the case where the constant is zero, we can load the
3371 // register directly from the zero register.
3372 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3373 Out, STI))
3374 return true;
3375 if (isABI_N32() || isABI_N64())
3376 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3377 else if (hasMips32r2()) {
3378 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3379 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3380 } else {
3381 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3382 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3383 }
3384 return false;
3385 }
3386
3387 MCSection *CS = getStreamer().getCurrentSectionOnly();
3388 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3389 // where appropriate.
3390 MCSection *ReadOnlySection = getContext().getELFSection(
3391 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3392
3393 MCSymbol *Sym = getContext().createTempSymbol();
3394 const MCExpr *LoSym =
3395 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3396 const MipsMCExpr *LoExpr =
3397 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3398
3399 getStreamer().SwitchSection(ReadOnlySection);
3400 getStreamer().EmitLabel(Sym, IDLoc);
3401 getStreamer().EmitIntValue(HiImmOp64, 4);
3402 getStreamer().EmitIntValue(LoImmOp64, 4);
3403 getStreamer().SwitchSection(CS);
3404
3405 if(emitPartialAddress(TOut, IDLoc, Sym))
3406 return true;
3407 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3408 MCOperand::createExpr(LoExpr), IDLoc, STI);
3409 }
3410 return false;
3411}
3412
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003413bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3414 MCStreamer &Out,
3415 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003416 MipsTargetStreamer &TOut = getTargetStreamer();
3417
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003418 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3419 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003420
3421 MCOperand Offset = Inst.getOperand(0);
3422 if (Offset.isExpr()) {
3423 Inst.clear();
3424 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003425 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3426 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3427 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003428 } else {
3429 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003430 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003431 // If offset fits into 11 bits then this instruction becomes microMIPS
3432 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003433 if (inMicroMipsMode())
3434 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003435 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003436 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003437 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003438 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003439 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003440 Inst.clear();
3441 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003442 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3443 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3444 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003445 }
3446 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003447 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003448
Zoran Jovanovicada70912015-09-07 11:56:37 +00003449 // If .set reorder is active and branch instruction has a delay slot,
3450 // emit a NOP after it.
3451 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3452 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003453 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003454
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003455 return false;
3456}
3457
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003458bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3459 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003460 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003461 const MCOperand &DstRegOp = Inst.getOperand(0);
3462 assert(DstRegOp.isReg() && "expected register operand kind");
3463
3464 const MCOperand &ImmOp = Inst.getOperand(1);
3465 assert(ImmOp.isImm() && "expected immediate operand kind");
3466
3467 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003468 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3469 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003470
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003471 bool IsLikely = false;
3472
Toma Tabacue1e460d2015-06-11 10:36:10 +00003473 unsigned OpCode = 0;
3474 switch(Inst.getOpcode()) {
3475 case Mips::BneImm:
3476 OpCode = Mips::BNE;
3477 break;
3478 case Mips::BeqImm:
3479 OpCode = Mips::BEQ;
3480 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003481 case Mips::BEQLImmMacro:
3482 OpCode = Mips::BEQL;
3483 IsLikely = true;
3484 break;
3485 case Mips::BNELImmMacro:
3486 OpCode = Mips::BNEL;
3487 IsLikely = true;
3488 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003489 default:
3490 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3491 break;
3492 }
3493
3494 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003495 if (ImmValue == 0) {
3496 if (IsLikely) {
3497 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3498 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3499 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3500 } else
3501 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3502 STI);
3503 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003504 warnIfNoMacro(IDLoc);
3505
3506 unsigned ATReg = getATReg(IDLoc);
3507 if (!ATReg)
3508 return true;
3509
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003510 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003511 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003512 return true;
3513
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003514 if (IsLikely) {
3515 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3516 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3517 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3518 } else
3519 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003520 }
3521 return false;
3522}
3523
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003524void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003525 const MCSubtargetInfo *STI, bool IsLoad,
3526 bool IsImmOpnd) {
3527 if (IsLoad) {
3528 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3529 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003530 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003531 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3532}
3533
3534void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3535 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3536 MipsTargetStreamer &TOut = getTargetStreamer();
3537
3538 unsigned DstReg = Inst.getOperand(0).getReg();
3539 unsigned BaseReg = Inst.getOperand(1).getReg();
3540
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003541 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003542 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3543 unsigned DstRegClassID =
3544 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3545 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3546 (DstRegClassID == Mips::GPR64RegClassID);
3547
3548 if (IsImmOpnd) {
3549 // Try to use DstReg as the temporary.
3550 if (IsGPR && (BaseReg != DstReg)) {
3551 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3552 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3553 STI);
3554 return;
3555 }
3556
Matheus Almeida7de68e72014-06-18 14:46:05 +00003557 // At this point we need AT to perform the expansions and we exit if it is
3558 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003559 unsigned ATReg = getATReg(IDLoc);
3560 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003561 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003562
3563 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3564 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3565 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003566 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003567
Daniel Sandersfba875f2016-04-29 13:43:45 +00003568 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003569 MCOperand LoOperand = MCOperand::createExpr(
3570 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3571 MCOperand HiOperand = MCOperand::createExpr(
3572 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003573
3574 // Try to use DstReg as the temporary.
3575 if (IsGPR && (BaseReg != DstReg)) {
3576 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3577 LoOperand, DstReg, IDLoc, STI);
3578 return;
3579 }
3580
3581 // At this point we need AT to perform the expansions and we exit if it is
3582 // not available.
3583 unsigned ATReg = getATReg(IDLoc);
3584 if (!ATReg)
3585 return;
3586
3587 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3588 LoOperand, ATReg, IDLoc, STI);
3589}
3590
3591void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3592 const MCSubtargetInfo *STI,
3593 bool IsImmOpnd) {
3594 MipsTargetStreamer &TOut = getTargetStreamer();
3595
3596 unsigned SrcReg = Inst.getOperand(0).getReg();
3597 unsigned BaseReg = Inst.getOperand(1).getReg();
3598
Daniel Sanders241c6792016-05-12 14:01:50 +00003599 if (IsImmOpnd) {
3600 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3601 Inst.getOperand(2).getImm(),
3602 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3603 return;
3604 }
3605
Daniel Sandersfba875f2016-04-29 13:43:45 +00003606 unsigned ATReg = getATReg(IDLoc);
3607 if (!ATReg)
3608 return;
3609
Daniel Sandersfba875f2016-04-29 13:43:45 +00003610 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003611 MCOperand LoOperand = MCOperand::createExpr(
3612 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3613 MCOperand HiOperand = MCOperand::createExpr(
3614 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003615 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3616 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003617}
3618
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003619bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3620 MCStreamer &Out,
3621 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003622 unsigned OpNum = Inst.getNumOperands();
3623 unsigned Opcode = Inst.getOpcode();
3624 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3625
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003626 assert(Inst.getOperand(OpNum - 1).isImm() &&
3627 Inst.getOperand(OpNum - 2).isReg() &&
3628 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003629
3630 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3631 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003632 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3633 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3634 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3635 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003636 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003637 if (inMicroMipsMode() && hasMips32r6())
3638 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3639 else
3640 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3641 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003642
3643 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003644 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003645 return false;
3646}
3647
Toma Tabacu1a108322015-06-17 13:20:24 +00003648bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003649 MCStreamer &Out,
3650 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003651 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003652 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003653 unsigned PseudoOpcode = Inst.getOpcode();
3654 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003655 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003656 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3657
3658 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003659 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003660
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003661 unsigned TrgReg;
3662 if (TrgOp.isReg())
3663 TrgReg = TrgOp.getReg();
3664 else if (TrgOp.isImm()) {
3665 warnIfNoMacro(IDLoc);
3666 EmittedNoMacroWarning = true;
3667
3668 TrgReg = getATReg(IDLoc);
3669 if (!TrgReg)
3670 return true;
3671
3672 switch(PseudoOpcode) {
3673 default:
3674 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3675 case Mips::BLTImmMacro:
3676 PseudoOpcode = Mips::BLT;
3677 break;
3678 case Mips::BLEImmMacro:
3679 PseudoOpcode = Mips::BLE;
3680 break;
3681 case Mips::BGEImmMacro:
3682 PseudoOpcode = Mips::BGE;
3683 break;
3684 case Mips::BGTImmMacro:
3685 PseudoOpcode = Mips::BGT;
3686 break;
3687 case Mips::BLTUImmMacro:
3688 PseudoOpcode = Mips::BLTU;
3689 break;
3690 case Mips::BLEUImmMacro:
3691 PseudoOpcode = Mips::BLEU;
3692 break;
3693 case Mips::BGEUImmMacro:
3694 PseudoOpcode = Mips::BGEU;
3695 break;
3696 case Mips::BGTUImmMacro:
3697 PseudoOpcode = Mips::BGTU;
3698 break;
3699 case Mips::BLTLImmMacro:
3700 PseudoOpcode = Mips::BLTL;
3701 break;
3702 case Mips::BLELImmMacro:
3703 PseudoOpcode = Mips::BLEL;
3704 break;
3705 case Mips::BGELImmMacro:
3706 PseudoOpcode = Mips::BGEL;
3707 break;
3708 case Mips::BGTLImmMacro:
3709 PseudoOpcode = Mips::BGTL;
3710 break;
3711 case Mips::BLTULImmMacro:
3712 PseudoOpcode = Mips::BLTUL;
3713 break;
3714 case Mips::BLEULImmMacro:
3715 PseudoOpcode = Mips::BLEUL;
3716 break;
3717 case Mips::BGEULImmMacro:
3718 PseudoOpcode = Mips::BGEUL;
3719 break;
3720 case Mips::BGTULImmMacro:
3721 PseudoOpcode = Mips::BGTUL;
3722 break;
3723 }
3724
3725 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003726 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003727 return true;
3728 }
3729
Toma Tabacu1a108322015-06-17 13:20:24 +00003730 switch (PseudoOpcode) {
3731 case Mips::BLT:
3732 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003733 case Mips::BLTL:
3734 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003735 AcceptsEquality = false;
3736 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003737 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3738 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003739 ZeroSrcOpcode = Mips::BGTZ;
3740 ZeroTrgOpcode = Mips::BLTZ;
3741 break;
3742 case Mips::BLE:
3743 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003744 case Mips::BLEL:
3745 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003746 AcceptsEquality = true;
3747 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003748 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3749 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003750 ZeroSrcOpcode = Mips::BGEZ;
3751 ZeroTrgOpcode = Mips::BLEZ;
3752 break;
3753 case Mips::BGE:
3754 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003755 case Mips::BGEL:
3756 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003757 AcceptsEquality = true;
3758 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003759 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3760 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003761 ZeroSrcOpcode = Mips::BLEZ;
3762 ZeroTrgOpcode = Mips::BGEZ;
3763 break;
3764 case Mips::BGT:
3765 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003766 case Mips::BGTL:
3767 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003768 AcceptsEquality = false;
3769 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003770 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3771 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003772 ZeroSrcOpcode = Mips::BLTZ;
3773 ZeroTrgOpcode = Mips::BGTZ;
3774 break;
3775 default:
3776 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3777 }
3778
Toma Tabacu1a108322015-06-17 13:20:24 +00003779 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3780 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3781 if (IsSrcRegZero && IsTrgRegZero) {
3782 // FIXME: All of these Opcode-specific if's are needed for compatibility
3783 // with GAS' behaviour. However, they may not generate the most efficient
3784 // code in some circumstances.
3785 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003786 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3787 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003788 return false;
3789 }
3790 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003791 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3792 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003793 Warning(IDLoc, "branch is always taken");
3794 return false;
3795 }
3796 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003797 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3798 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003799 Warning(IDLoc, "branch is always taken");
3800 return false;
3801 }
3802 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003803 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3804 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003805 return false;
3806 }
3807 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003808 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3809 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003810 return false;
3811 }
3812 if (AcceptsEquality) {
3813 // If both registers are $0 and the pseudo-branch accepts equality, it
3814 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003815 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3816 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003817 Warning(IDLoc, "branch is always taken");
3818 return false;
3819 }
3820 // If both registers are $0 and the pseudo-branch does not accept
3821 // equality, it will never be taken, so we don't have to emit anything.
3822 return false;
3823 }
3824 if (IsSrcRegZero || IsTrgRegZero) {
3825 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3826 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3827 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3828 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3829 // the pseudo-branch will never be taken, so we don't emit anything.
3830 // This only applies to unsigned pseudo-branches.
3831 return false;
3832 }
3833 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3834 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3835 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3836 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3837 // the pseudo-branch will always be taken, so we emit an unconditional
3838 // branch.
3839 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003840 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3841 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003842 Warning(IDLoc, "branch is always taken");
3843 return false;
3844 }
3845 if (IsUnsigned) {
3846 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3847 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3848 // the pseudo-branch will be taken only when the non-zero register is
3849 // different from 0, so we emit a BNEZ.
3850 //
3851 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3852 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3853 // the pseudo-branch will be taken only when the non-zero register is
3854 // equal to 0, so we emit a BEQZ.
3855 //
3856 // Because only BLEU and BGEU branch on equality, we can use the
3857 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003858 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3859 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3860 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003861 return false;
3862 }
3863 // If we have a signed pseudo-branch and one of the registers is $0,
3864 // we can use an appropriate compare-to-zero branch. We select which one
3865 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003866 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3867 IsSrcRegZero ? TrgReg : SrcReg,
3868 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003869 return false;
3870 }
3871
3872 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3873 // expansions. If it is not available, we return.
3874 unsigned ATRegNum = getATReg(IDLoc);
3875 if (!ATRegNum)
3876 return true;
3877
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003878 if (!EmittedNoMacroWarning)
3879 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003880
3881 // SLT fits well with 2 of our 4 pseudo-branches:
3882 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3883 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3884 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3885 // This is accomplished by using a BNEZ with the result of the SLT.
3886 //
3887 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3888 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3889 // Because only BGE and BLE branch on equality, we can use the
3890 // AcceptsEquality variable to decide when to emit the BEQZ.
3891 // Note that the order of the SLT arguments doesn't change between
3892 // opposites.
3893 //
3894 // The same applies to the unsigned variants, except that SLTu is used
3895 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003896 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3897 ReverseOrderSLT ? TrgReg : SrcReg,
3898 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003899
Daniel Sandersa736b372016-04-29 13:33:12 +00003900 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3901 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3902 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3903 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003904 return false;
3905}
3906
Simon Dardis509da1a2017-02-13 16:06:48 +00003907// Expand a integer division macro.
3908//
3909// Notably we don't have to emit a warning when encountering $rt as the $zero
3910// register, or 0 as an immediate. processInstruction() has already done that.
3911//
3912// The destination register can only be $zero when expanding (S)DivIMacro or
3913// D(S)DivMacro.
3914
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003915bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3916 const MCSubtargetInfo *STI, const bool IsMips64,
3917 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003918 MipsTargetStreamer &TOut = getTargetStreamer();
3919
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003920 warnIfNoMacro(IDLoc);
3921
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003922 const MCOperand &RdRegOp = Inst.getOperand(0);
3923 assert(RdRegOp.isReg() && "expected register operand kind");
3924 unsigned RdReg = RdRegOp.getReg();
3925
3926 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003927 assert(RsRegOp.isReg() && "expected register operand kind");
3928 unsigned RsReg = RsRegOp.getReg();
3929
Simon Dardis12850ee2017-01-31 10:49:24 +00003930 unsigned RtReg;
3931 int64_t ImmValue;
3932
3933 const MCOperand &RtOp = Inst.getOperand(2);
3934 assert((RtOp.isReg() || RtOp.isImm()) &&
3935 "expected register or immediate operand kind");
3936 if (RtOp.isReg())
3937 RtReg = RtOp.getReg();
3938 else
3939 ImmValue = RtOp.getImm();
3940
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003941 unsigned DivOp;
3942 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003943 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003944
3945 if (IsMips64) {
3946 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3947 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003948 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003949 } else {
3950 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3951 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003952 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003953 }
3954
3955 bool UseTraps = useTraps();
3956
Simon Dardis12850ee2017-01-31 10:49:24 +00003957 if (RtOp.isImm()) {
3958 unsigned ATReg = getATReg(IDLoc);
3959 if (!ATReg)
3960 return true;
3961
3962 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003963 if (UseTraps)
3964 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3965 else
3966 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3967 return false;
3968 }
3969
3970 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003971 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003972 return false;
3973 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003974 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003975 return false;
3976 } else {
3977 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3978 false, Inst.getLoc(), Out, STI))
3979 return true;
3980 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3981 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3982 return false;
3983 }
3984 return true;
3985 }
3986
Simon Dardis509da1a2017-02-13 16:06:48 +00003987 // If the macro expansion of (d)div(u) would always trap or break, insert
3988 // the trap/break and exit. This gives a different result to GAS. GAS has
3989 // an inconsistency/missed optimization in that not all cases are handled
3990 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003991 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003992 if (UseTraps) {
3993 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003994 return false;
3995 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003996 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3997 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003998 }
3999
Simon Dardis509da1a2017-02-13 16:06:48 +00004000 // Temporary label for first branch traget
4001 MCContext &Context = TOut.getStreamer().getContext();
4002 MCSymbol *BrTarget;
4003 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004004
4005 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004006 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004007 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004008 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004009 BrTarget = Context.createTempSymbol();
4010 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4011 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004012 }
4013
Daniel Sandersa736b372016-04-29 13:33:12 +00004014 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004015
4016 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004017 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004018
4019 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004020 if (!UseTraps)
4021 TOut.getStreamer().EmitLabel(BrTarget);
4022
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004023 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004024 return false;
4025 }
4026
4027 unsigned ATReg = getATReg(IDLoc);
4028 if (!ATReg)
4029 return true;
4030
Simon Dardis509da1a2017-02-13 16:06:48 +00004031 if (!UseTraps)
4032 TOut.getStreamer().EmitLabel(BrTarget);
4033
Daniel Sandersa736b372016-04-29 13:33:12 +00004034 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004035
4036 // Temporary label for the second branch target.
4037 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4038 MCOperand LabelOpEnd =
4039 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4040
4041 // Branch to the mflo instruction.
4042 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4043
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004044 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004045 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4046 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004047 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004048 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004049 }
4050
4051 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004052 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004053 else {
4054 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004055 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004056 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4057 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004058 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004059
4060 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004061 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004062 return false;
4063}
4064
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004065bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004066 SMLoc IDLoc, MCStreamer &Out,
4067 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004068 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004069
4070 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4071 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4072 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4073
4074 unsigned FirstReg = Inst.getOperand(0).getReg();
4075 unsigned SecondReg = Inst.getOperand(1).getReg();
4076 unsigned ThirdReg = Inst.getOperand(2).getReg();
4077
4078 if (hasMips1() && !hasMips2()) {
4079 unsigned ATReg = getATReg(IDLoc);
4080 if (!ATReg)
4081 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004082 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4083 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4084 TOut.emitNop(IDLoc, STI);
4085 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4086 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4087 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4088 TOut.emitNop(IDLoc, STI);
4089 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4090 : Mips::CVT_W_S,
4091 FirstReg, SecondReg, IDLoc, STI);
4092 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4093 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004094 return false;
4095 }
4096
Daniel Sandersa736b372016-04-29 13:33:12 +00004097 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4098 : Mips::TRUNC_W_S,
4099 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004100
4101 return false;
4102}
4103
Daniel Sanders6394ee52015-10-15 14:52:58 +00004104bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004105 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004106 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004107 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004108 }
4109
Toma Tabacud88d79c2015-06-23 14:39:42 +00004110 const MCOperand &DstRegOp = Inst.getOperand(0);
4111 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004112 const MCOperand &SrcRegOp = Inst.getOperand(1);
4113 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004114 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4115 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4116
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004117 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004118 unsigned DstReg = DstRegOp.getReg();
4119 unsigned SrcReg = SrcRegOp.getReg();
4120 int64_t OffsetValue = OffsetImmOp.getImm();
4121
4122 // NOTE: We always need AT for ULHU, as it is always used as the source
4123 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004124 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004125 unsigned ATReg = getATReg(IDLoc);
4126 if (!ATReg)
4127 return true;
4128
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004129 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4130 if (IsLargeOffset) {
4131 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4132 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004133 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004134 }
4135
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004136 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4137 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4138 if (isLittle())
4139 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004140
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004141 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4142 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004143
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004144 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4145 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004146
Daniel Sandersa736b372016-04-29 13:33:12 +00004147 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004148 FirstOffset, IDLoc, STI);
4149 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004150 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004151 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004152
4153 return false;
4154}
4155
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004156bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004157 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004158 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004159 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004160 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004161
4162 const MCOperand &DstRegOp = Inst.getOperand(0);
4163 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004164 const MCOperand &SrcRegOp = Inst.getOperand(1);
4165 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004166 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4167 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4168
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004169 MipsTargetStreamer &TOut = getTargetStreamer();
4170 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004171 unsigned SrcReg = SrcRegOp.getReg();
4172 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004173
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004174 warnIfNoMacro(IDLoc);
4175 unsigned ATReg = getATReg(IDLoc);
4176 if (!ATReg)
4177 return true;
4178
4179 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4180 if (IsLargeOffset) {
4181 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4182 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004183 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004184 }
4185
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004186 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4187 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4188 if (isLittle())
4189 std::swap(FirstOffset, SecondOffset);
4190
4191 if (IsLargeOffset) {
4192 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4193 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4194 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4195 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4196 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4197 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004198 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004199 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4200 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4201 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004202 }
4203
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004204 return false;
4205}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004206
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004207bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4208 const MCSubtargetInfo *STI) {
4209 if (hasMips32r6() || hasMips64r6()) {
4210 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4211 }
4212
4213 const MCOperand &DstRegOp = Inst.getOperand(0);
4214 assert(DstRegOp.isReg() && "expected register operand kind");
4215 const MCOperand &SrcRegOp = Inst.getOperand(1);
4216 assert(SrcRegOp.isReg() && "expected register operand kind");
4217 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4218 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4219
4220 MipsTargetStreamer &TOut = getTargetStreamer();
4221 unsigned DstReg = DstRegOp.getReg();
4222 unsigned SrcReg = SrcRegOp.getReg();
4223 int64_t OffsetValue = OffsetImmOp.getImm();
4224
4225 // Compute left/right load/store offsets.
4226 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4227 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4228 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4229 if (isLittle())
4230 std::swap(LxlOffset, LxrOffset);
4231
4232 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4233 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4234 unsigned TmpReg = SrcReg;
4235 if (IsLargeOffset || DoMove) {
4236 warnIfNoMacro(IDLoc);
4237 TmpReg = getATReg(IDLoc);
4238 if (!TmpReg)
4239 return true;
4240 }
4241
4242 if (IsLargeOffset) {
4243 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4244 IDLoc, Out, STI))
4245 return true;
4246 }
4247
4248 if (DoMove)
4249 std::swap(DstReg, TmpReg);
4250
4251 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4252 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4253 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4254 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4255
4256 if (DoMove)
4257 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004258
4259 return false;
4260}
4261
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004262bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004263 MCStreamer &Out,
4264 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004265 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004266
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004267 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4268 assert(Inst.getOperand(0).isReg() &&
4269 Inst.getOperand(1).isReg() &&
4270 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004271
4272 unsigned ATReg = Mips::NoRegister;
4273 unsigned FinalDstReg = Mips::NoRegister;
4274 unsigned DstReg = Inst.getOperand(0).getReg();
4275 unsigned SrcReg = Inst.getOperand(1).getReg();
4276 int64_t ImmValue = Inst.getOperand(2).getImm();
4277
Simon Dardisaa208812017-02-24 14:34:32 +00004278 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004279
4280 unsigned FinalOpcode = Inst.getOpcode();
4281
4282 if (DstReg == SrcReg) {
4283 ATReg = getATReg(Inst.getLoc());
4284 if (!ATReg)
4285 return true;
4286 FinalDstReg = DstReg;
4287 DstReg = ATReg;
4288 }
4289
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004290 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004291 switch (FinalOpcode) {
4292 default:
4293 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004294 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004295 FinalOpcode = Mips::ADD;
4296 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004297 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004298 FinalOpcode = Mips::ADDu;
4299 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004300 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004301 FinalOpcode = Mips::AND;
4302 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004303 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004304 FinalOpcode = Mips::NOR;
4305 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004306 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004307 FinalOpcode = Mips::OR;
4308 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004309 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004310 FinalOpcode = Mips::SLT;
4311 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004312 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004313 FinalOpcode = Mips::SLTu;
4314 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004315 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004316 FinalOpcode = Mips::XOR;
4317 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004318 case Mips::ADDi_MM:
4319 FinalOpcode = Mips::ADD_MM;
4320 break;
4321 case Mips::ADDiu_MM:
4322 FinalOpcode = Mips::ADDu_MM;
4323 break;
4324 case Mips::ANDi_MM:
4325 FinalOpcode = Mips::AND_MM;
4326 break;
4327 case Mips::ORi_MM:
4328 FinalOpcode = Mips::OR_MM;
4329 break;
4330 case Mips::SLTi_MM:
4331 FinalOpcode = Mips::SLT_MM;
4332 break;
4333 case Mips::SLTiu_MM:
4334 FinalOpcode = Mips::SLTu_MM;
4335 break;
4336 case Mips::XORi_MM:
4337 FinalOpcode = Mips::XOR_MM;
4338 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004339 case Mips::ANDi64:
4340 FinalOpcode = Mips::AND64;
4341 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004342 case Mips::NORImm64:
4343 FinalOpcode = Mips::NOR64;
4344 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004345 case Mips::ORi64:
4346 FinalOpcode = Mips::OR64;
4347 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004348 case Mips::SLTImm64:
4349 FinalOpcode = Mips::SLT64;
4350 break;
4351 case Mips::SLTUImm64:
4352 FinalOpcode = Mips::SLTu64;
4353 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004354 case Mips::XORi64:
4355 FinalOpcode = Mips::XOR64;
4356 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004357 }
4358
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004359 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004360 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004361 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004362 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004363 return false;
4364 }
4365 return true;
4366}
4367
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004368bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4369 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004370 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004371 unsigned ATReg = Mips::NoRegister;
4372 unsigned DReg = Inst.getOperand(0).getReg();
4373 unsigned SReg = Inst.getOperand(1).getReg();
4374 unsigned TReg = Inst.getOperand(2).getReg();
4375 unsigned TmpReg = DReg;
4376
4377 unsigned FirstShift = Mips::NOP;
4378 unsigned SecondShift = Mips::NOP;
4379
4380 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004381 if (DReg == SReg) {
4382 TmpReg = getATReg(Inst.getLoc());
4383 if (!TmpReg)
4384 return true;
4385 }
4386
4387 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004388 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4389 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004390 return false;
4391 }
4392
4393 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004394 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004395 return false;
4396 }
4397
4398 return true;
4399 }
4400
4401 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004402 switch (Inst.getOpcode()) {
4403 default:
4404 llvm_unreachable("unexpected instruction opcode");
4405 case Mips::ROL:
4406 FirstShift = Mips::SRLV;
4407 SecondShift = Mips::SLLV;
4408 break;
4409 case Mips::ROR:
4410 FirstShift = Mips::SLLV;
4411 SecondShift = Mips::SRLV;
4412 break;
4413 }
4414
4415 ATReg = getATReg(Inst.getLoc());
4416 if (!ATReg)
4417 return true;
4418
Daniel Sandersa736b372016-04-29 13:33:12 +00004419 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4420 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4421 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4422 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004423
4424 return false;
4425 }
4426
4427 return true;
4428}
4429
4430bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004431 MCStreamer &Out,
4432 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004433 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004434 unsigned ATReg = Mips::NoRegister;
4435 unsigned DReg = Inst.getOperand(0).getReg();
4436 unsigned SReg = Inst.getOperand(1).getReg();
4437 int64_t ImmValue = Inst.getOperand(2).getImm();
4438
4439 unsigned FirstShift = Mips::NOP;
4440 unsigned SecondShift = Mips::NOP;
4441
4442 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004443 if (Inst.getOpcode() == Mips::ROLImm) {
4444 uint64_t MaxShift = 32;
4445 uint64_t ShiftValue = ImmValue;
4446 if (ImmValue != 0)
4447 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004448 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004449 return false;
4450 }
4451
4452 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004453 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004454 return false;
4455 }
4456
4457 return true;
4458 }
4459
4460 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004461 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004462 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004463 return false;
4464 }
4465
4466 switch (Inst.getOpcode()) {
4467 default:
4468 llvm_unreachable("unexpected instruction opcode");
4469 case Mips::ROLImm:
4470 FirstShift = Mips::SLL;
4471 SecondShift = Mips::SRL;
4472 break;
4473 case Mips::RORImm:
4474 FirstShift = Mips::SRL;
4475 SecondShift = Mips::SLL;
4476 break;
4477 }
4478
4479 ATReg = getATReg(Inst.getLoc());
4480 if (!ATReg)
4481 return true;
4482
Daniel Sandersa736b372016-04-29 13:33:12 +00004483 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4484 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4485 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004486
4487 return false;
4488 }
4489
4490 return true;
4491}
4492
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004493bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4494 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004495 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004496 unsigned ATReg = Mips::NoRegister;
4497 unsigned DReg = Inst.getOperand(0).getReg();
4498 unsigned SReg = Inst.getOperand(1).getReg();
4499 unsigned TReg = Inst.getOperand(2).getReg();
4500 unsigned TmpReg = DReg;
4501
4502 unsigned FirstShift = Mips::NOP;
4503 unsigned SecondShift = Mips::NOP;
4504
4505 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004506 if (TmpReg == SReg) {
4507 TmpReg = getATReg(Inst.getLoc());
4508 if (!TmpReg)
4509 return true;
4510 }
4511
4512 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004513 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4514 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004515 return false;
4516 }
4517
4518 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004519 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004520 return false;
4521 }
4522
4523 return true;
4524 }
4525
4526 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004527 switch (Inst.getOpcode()) {
4528 default:
4529 llvm_unreachable("unexpected instruction opcode");
4530 case Mips::DROL:
4531 FirstShift = Mips::DSRLV;
4532 SecondShift = Mips::DSLLV;
4533 break;
4534 case Mips::DROR:
4535 FirstShift = Mips::DSLLV;
4536 SecondShift = Mips::DSRLV;
4537 break;
4538 }
4539
4540 ATReg = getATReg(Inst.getLoc());
4541 if (!ATReg)
4542 return true;
4543
Daniel Sandersa736b372016-04-29 13:33:12 +00004544 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4545 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4546 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4547 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004548
4549 return false;
4550 }
4551
4552 return true;
4553}
4554
4555bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004556 MCStreamer &Out,
4557 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004558 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004559 unsigned ATReg = Mips::NoRegister;
4560 unsigned DReg = Inst.getOperand(0).getReg();
4561 unsigned SReg = Inst.getOperand(1).getReg();
4562 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4563
4564 unsigned FirstShift = Mips::NOP;
4565 unsigned SecondShift = Mips::NOP;
4566
4567 MCInst TmpInst;
4568
4569 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004570 unsigned FinalOpcode = Mips::NOP;
4571 if (ImmValue == 0)
4572 FinalOpcode = Mips::DROTR;
4573 else if (ImmValue % 32 == 0)
4574 FinalOpcode = Mips::DROTR32;
4575 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4576 if (Inst.getOpcode() == Mips::DROLImm)
4577 FinalOpcode = Mips::DROTR32;
4578 else
4579 FinalOpcode = Mips::DROTR;
4580 } else if (ImmValue >= 33) {
4581 if (Inst.getOpcode() == Mips::DROLImm)
4582 FinalOpcode = Mips::DROTR;
4583 else
4584 FinalOpcode = Mips::DROTR32;
4585 }
4586
4587 uint64_t ShiftValue = ImmValue % 32;
4588 if (Inst.getOpcode() == Mips::DROLImm)
4589 ShiftValue = (32 - ImmValue % 32) % 32;
4590
Daniel Sandersa736b372016-04-29 13:33:12 +00004591 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004592
4593 return false;
4594 }
4595
4596 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004597 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004598 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004599 return false;
4600 }
4601
4602 switch (Inst.getOpcode()) {
4603 default:
4604 llvm_unreachable("unexpected instruction opcode");
4605 case Mips::DROLImm:
4606 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4607 FirstShift = Mips::DSLL;
4608 SecondShift = Mips::DSRL32;
4609 }
4610 if (ImmValue == 32) {
4611 FirstShift = Mips::DSLL32;
4612 SecondShift = Mips::DSRL32;
4613 }
4614 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4615 FirstShift = Mips::DSLL32;
4616 SecondShift = Mips::DSRL;
4617 }
4618 break;
4619 case Mips::DRORImm:
4620 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4621 FirstShift = Mips::DSRL;
4622 SecondShift = Mips::DSLL32;
4623 }
4624 if (ImmValue == 32) {
4625 FirstShift = Mips::DSRL32;
4626 SecondShift = Mips::DSLL32;
4627 }
4628 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4629 FirstShift = Mips::DSRL32;
4630 SecondShift = Mips::DSLL;
4631 }
4632 break;
4633 }
4634
4635 ATReg = getATReg(Inst.getLoc());
4636 if (!ATReg)
4637 return true;
4638
Daniel Sandersa736b372016-04-29 13:33:12 +00004639 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4640 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4641 Inst.getLoc(), STI);
4642 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004643
4644 return false;
4645 }
4646
4647 return true;
4648}
4649
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004650bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4651 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004652 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004653 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4654 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4655
Daniel Sandersa736b372016-04-29 13:33:12 +00004656 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004657 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004658 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004659 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004660 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4661 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004662
4663 return false;
4664}
4665
Simon Dardis3c82a642017-02-08 16:25:05 +00004666bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4667 const MCSubtargetInfo *STI) {
4668 MipsTargetStreamer &TOut = getTargetStreamer();
4669 unsigned ATReg = Mips::NoRegister;
4670 unsigned DstReg = Inst.getOperand(0).getReg();
4671 unsigned SrcReg = Inst.getOperand(1).getReg();
4672 int32_t ImmValue = Inst.getOperand(2).getImm();
4673
4674 ATReg = getATReg(IDLoc);
4675 if (!ATReg)
4676 return true;
4677
4678 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4679
4680 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4681 SrcReg, ATReg, IDLoc, STI);
4682
4683 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4684
4685 return false;
4686}
4687
4688bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4689 const MCSubtargetInfo *STI) {
4690 MipsTargetStreamer &TOut = getTargetStreamer();
4691 unsigned ATReg = Mips::NoRegister;
4692 unsigned DstReg = Inst.getOperand(0).getReg();
4693 unsigned SrcReg = Inst.getOperand(1).getReg();
4694 unsigned TmpReg = Inst.getOperand(2).getReg();
4695
4696 ATReg = getATReg(Inst.getLoc());
4697 if (!ATReg)
4698 return true;
4699
4700 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4701 SrcReg, TmpReg, IDLoc, STI);
4702
4703 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4704
4705 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4706 DstReg, DstReg, 0x1F, IDLoc, STI);
4707
4708 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4709
4710 if (useTraps()) {
4711 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4712 } else {
4713 MCContext & Context = TOut.getStreamer().getContext();
4714 MCSymbol * BrTarget = Context.createTempSymbol();
4715 MCOperand LabelOp =
4716 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4717
4718 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4719 if (AssemblerOptions.back()->isReorder())
4720 TOut.emitNop(IDLoc, STI);
4721 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4722
4723 TOut.getStreamer().EmitLabel(BrTarget);
4724 }
4725 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4726
4727 return false;
4728}
4729
4730bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4731 const MCSubtargetInfo *STI) {
4732 MipsTargetStreamer &TOut = getTargetStreamer();
4733 unsigned ATReg = Mips::NoRegister;
4734 unsigned DstReg = Inst.getOperand(0).getReg();
4735 unsigned SrcReg = Inst.getOperand(1).getReg();
4736 unsigned TmpReg = Inst.getOperand(2).getReg();
4737
4738 ATReg = getATReg(IDLoc);
4739 if (!ATReg)
4740 return true;
4741
4742 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4743 SrcReg, TmpReg, IDLoc, STI);
4744
4745 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4746 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4747 if (useTraps()) {
4748 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4749 } else {
4750 MCContext & Context = TOut.getStreamer().getContext();
4751 MCSymbol * BrTarget = Context.createTempSymbol();
4752 MCOperand LabelOp =
4753 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4754
4755 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4756 if (AssemblerOptions.back()->isReorder())
4757 TOut.emitNop(IDLoc, STI);
4758 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4759
4760 TOut.getStreamer().EmitLabel(BrTarget);
4761 }
4762
4763 return false;
4764}
4765
4766bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4767 const MCSubtargetInfo *STI) {
4768 MipsTargetStreamer &TOut = getTargetStreamer();
4769 unsigned DstReg = Inst.getOperand(0).getReg();
4770 unsigned SrcReg = Inst.getOperand(1).getReg();
4771 unsigned TmpReg = Inst.getOperand(2).getReg();
4772
4773 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4774 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4775
4776 return false;
4777}
4778
Simon Dardisaff4d142016-10-18 14:28:00 +00004779// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4780// lw $<reg+1>>, offset+4($reg2)'
4781// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4782// sw $<reg+1>>, offset+4($reg2)'
4783// for O32.
4784bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4785 MCStreamer &Out,
4786 const MCSubtargetInfo *STI,
4787 bool IsLoad) {
4788 if (!isABI_O32())
4789 return true;
4790
4791 warnIfNoMacro(IDLoc);
4792
4793 MipsTargetStreamer &TOut = getTargetStreamer();
4794 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4795 unsigned FirstReg = Inst.getOperand(0).getReg();
4796 unsigned SecondReg = nextReg(FirstReg);
4797 unsigned BaseReg = Inst.getOperand(1).getReg();
4798 if (!SecondReg)
4799 return true;
4800
4801 warnIfRegIndexIsAT(FirstReg, IDLoc);
4802
4803 assert(Inst.getOperand(2).isImm() &&
4804 "Offset for load macro is not immediate!");
4805
4806 MCOperand &FirstOffset = Inst.getOperand(2);
4807 signed NextOffset = FirstOffset.getImm() + 4;
4808 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4809
4810 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4811 return true;
4812
4813 // For loads, clobber the base register with the second load instead of the
4814 // first if the BaseReg == FirstReg.
4815 if (FirstReg != BaseReg || !IsLoad) {
4816 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4817 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4818 } else {
4819 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4820 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4821 }
4822
4823 return false;
4824}
4825
Simon Dardis43115a12016-11-21 20:30:41 +00004826bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4827 const MCSubtargetInfo *STI) {
4828
4829 warnIfNoMacro(IDLoc);
4830 MipsTargetStreamer &TOut = getTargetStreamer();
4831
4832 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4833 Inst.getOperand(2).getReg() != Mips::ZERO) {
4834 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4835 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4836 IDLoc, STI);
4837 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4838 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4839 return false;
4840 }
4841
4842 unsigned Reg = 0;
4843 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4844 Reg = Inst.getOperand(2).getReg();
4845 } else {
4846 Reg = Inst.getOperand(1).getReg();
4847 }
4848 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4849 return false;
4850}
4851
4852bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4853 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004854 warnIfNoMacro(IDLoc);
4855 MipsTargetStreamer &TOut = getTargetStreamer();
4856
4857 unsigned Opc;
4858 int64_t Imm = Inst.getOperand(2).getImm();
4859 unsigned Reg = Inst.getOperand(1).getReg();
4860
4861 if (Imm == 0) {
4862 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4863 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4864 return false;
4865 } else {
4866
4867 if (Reg == Mips::ZERO) {
4868 Warning(IDLoc, "comparison is always false");
4869 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4870 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4871 return false;
4872 }
4873
4874 if (Imm > -0x8000 && Imm < 0) {
4875 Imm = -Imm;
4876 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4877 } else {
4878 Opc = Mips::XORi;
4879 }
4880 }
4881 if (!isUInt<16>(Imm)) {
4882 unsigned ATReg = getATReg(IDLoc);
4883 if (!ATReg)
4884 return true;
4885
4886 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4887 Out, STI))
4888 return true;
4889
4890 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4891 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4892 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4893 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4894 return false;
4895 }
4896
4897 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4898 Imm, IDLoc, STI);
4899 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4900 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4901 return false;
4902}
4903
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004904// Map the DSP accumulator and control register to the corresponding gpr
4905// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4906// do not map the DSP registers contigously to gpr registers.
4907static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4908 switch (Inst.getOpcode()) {
4909 case Mips::MFTLO:
4910 case Mips::MTTLO:
4911 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4912 case Mips::AC0:
4913 return Mips::ZERO;
4914 case Mips::AC1:
4915 return Mips::A0;
4916 case Mips::AC2:
4917 return Mips::T0;
4918 case Mips::AC3:
4919 return Mips::T4;
4920 default:
4921 llvm_unreachable("Unknown register for 'mttr' alias!");
4922 }
4923 case Mips::MFTHI:
4924 case Mips::MTTHI:
4925 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4926 case Mips::AC0:
4927 return Mips::AT;
4928 case Mips::AC1:
4929 return Mips::A1;
4930 case Mips::AC2:
4931 return Mips::T1;
4932 case Mips::AC3:
4933 return Mips::T5;
4934 default:
4935 llvm_unreachable("Unknown register for 'mttr' alias!");
4936 }
4937 case Mips::MFTACX:
4938 case Mips::MTTACX:
4939 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4940 case Mips::AC0:
4941 return Mips::V0;
4942 case Mips::AC1:
4943 return Mips::A2;
4944 case Mips::AC2:
4945 return Mips::T2;
4946 case Mips::AC3:
4947 return Mips::T6;
4948 default:
4949 llvm_unreachable("Unknown register for 'mttr' alias!");
4950 }
4951 case Mips::MFTDSP:
4952 case Mips::MTTDSP:
4953 return Mips::S0;
4954 default:
4955 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4956 }
4957}
4958
4959// Map the floating point register operand to the corresponding register
4960// operand.
4961static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4962 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4963 case Mips::F0: return Mips::ZERO;
4964 case Mips::F1: return Mips::AT;
4965 case Mips::F2: return Mips::V0;
4966 case Mips::F3: return Mips::V1;
4967 case Mips::F4: return Mips::A0;
4968 case Mips::F5: return Mips::A1;
4969 case Mips::F6: return Mips::A2;
4970 case Mips::F7: return Mips::A3;
4971 case Mips::F8: return Mips::T0;
4972 case Mips::F9: return Mips::T1;
4973 case Mips::F10: return Mips::T2;
4974 case Mips::F11: return Mips::T3;
4975 case Mips::F12: return Mips::T4;
4976 case Mips::F13: return Mips::T5;
4977 case Mips::F14: return Mips::T6;
4978 case Mips::F15: return Mips::T7;
4979 case Mips::F16: return Mips::S0;
4980 case Mips::F17: return Mips::S1;
4981 case Mips::F18: return Mips::S2;
4982 case Mips::F19: return Mips::S3;
4983 case Mips::F20: return Mips::S4;
4984 case Mips::F21: return Mips::S5;
4985 case Mips::F22: return Mips::S6;
4986 case Mips::F23: return Mips::S7;
4987 case Mips::F24: return Mips::T8;
4988 case Mips::F25: return Mips::T9;
4989 case Mips::F26: return Mips::K0;
4990 case Mips::F27: return Mips::K1;
4991 case Mips::F28: return Mips::GP;
4992 case Mips::F29: return Mips::SP;
4993 case Mips::F30: return Mips::FP;
4994 case Mips::F31: return Mips::RA;
4995 default: llvm_unreachable("Unknown register for mttc1 alias!");
4996 }
4997}
4998
4999// Map the coprocessor operand the corresponding gpr register operand.
5000static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5001 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5002 case Mips::COP00: return Mips::ZERO;
5003 case Mips::COP01: return Mips::AT;
5004 case Mips::COP02: return Mips::V0;
5005 case Mips::COP03: return Mips::V1;
5006 case Mips::COP04: return Mips::A0;
5007 case Mips::COP05: return Mips::A1;
5008 case Mips::COP06: return Mips::A2;
5009 case Mips::COP07: return Mips::A3;
5010 case Mips::COP08: return Mips::T0;
5011 case Mips::COP09: return Mips::T1;
5012 case Mips::COP010: return Mips::T2;
5013 case Mips::COP011: return Mips::T3;
5014 case Mips::COP012: return Mips::T4;
5015 case Mips::COP013: return Mips::T5;
5016 case Mips::COP014: return Mips::T6;
5017 case Mips::COP015: return Mips::T7;
5018 case Mips::COP016: return Mips::S0;
5019 case Mips::COP017: return Mips::S1;
5020 case Mips::COP018: return Mips::S2;
5021 case Mips::COP019: return Mips::S3;
5022 case Mips::COP020: return Mips::S4;
5023 case Mips::COP021: return Mips::S5;
5024 case Mips::COP022: return Mips::S6;
5025 case Mips::COP023: return Mips::S7;
5026 case Mips::COP024: return Mips::T8;
5027 case Mips::COP025: return Mips::T9;
5028 case Mips::COP026: return Mips::K0;
5029 case Mips::COP027: return Mips::K1;
5030 case Mips::COP028: return Mips::GP;
5031 case Mips::COP029: return Mips::SP;
5032 case Mips::COP030: return Mips::FP;
5033 case Mips::COP031: return Mips::RA;
5034 default: llvm_unreachable("Unknown register for mttc0 alias!");
5035 }
5036}
5037
5038/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5039/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5040bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5041 const MCSubtargetInfo *STI) {
5042 MipsTargetStreamer &TOut = getTargetStreamer();
5043 unsigned rd = 0;
5044 unsigned u = 1;
5045 unsigned sel = 0;
5046 unsigned h = 0;
5047 bool IsMFTR = false;
5048 switch (Inst.getOpcode()) {
5049 case Mips::MFTC0:
5050 IsMFTR = true;
5051 LLVM_FALLTHROUGH;
5052 case Mips::MTTC0:
5053 u = 0;
5054 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5055 sel = Inst.getOperand(2).getImm();
5056 break;
5057 case Mips::MFTGPR:
5058 IsMFTR = true;
5059 LLVM_FALLTHROUGH;
5060 case Mips::MTTGPR:
5061 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5062 break;
5063 case Mips::MFTLO:
5064 case Mips::MFTHI:
5065 case Mips::MFTACX:
5066 case Mips::MFTDSP:
5067 IsMFTR = true;
5068 LLVM_FALLTHROUGH;
5069 case Mips::MTTLO:
5070 case Mips::MTTHI:
5071 case Mips::MTTACX:
5072 case Mips::MTTDSP:
5073 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5074 sel = 1;
5075 break;
5076 case Mips::MFTHC1:
5077 h = 1;
5078 LLVM_FALLTHROUGH;
5079 case Mips::MFTC1:
5080 IsMFTR = true;
5081 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5082 sel = 2;
5083 break;
5084 case Mips::MTTHC1:
5085 h = 1;
5086 LLVM_FALLTHROUGH;
5087 case Mips::MTTC1:
5088 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5089 sel = 2;
5090 break;
5091 case Mips::CFTC1:
5092 IsMFTR = true;
5093 LLVM_FALLTHROUGH;
5094 case Mips::CTTC1:
5095 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5096 sel = 3;
5097 break;
5098 }
5099 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5100 unsigned Op1 =
5101 IsMFTR ? rd
5102 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5103 : Inst.getOperand(0).getReg());
5104
5105 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5106 STI);
5107 return false;
5108}
5109
Daniel Sandersc5537422016-07-27 13:49:44 +00005110unsigned
5111MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5112 const OperandVector &Operands) {
5113 switch (Inst.getOpcode()) {
5114 default:
5115 return Match_Success;
5116 case Mips::DATI:
5117 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005118 if (static_cast<MipsOperand &>(*Operands[1])
5119 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5120 return Match_Success;
5121 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005122 }
5123}
Simon Dardis730fdb72017-01-16 13:55:58 +00005124
Matheus Almeida595fcab2014-06-11 15:05:56 +00005125unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005126 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005127 // As described by the MIPSR6 spec, daui must not use the zero operand for
5128 // its source operand.
5129 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005130 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5131 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5132 return Match_RequiresNoZeroRegister;
5133 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005134 // As described by the Mips32r2 spec, the registers Rd and Rs for
5135 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005136 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005137 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005138 case Mips::JALR_HB:
5139 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005140 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005141 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5142 return Match_RequiresDifferentSrcAndDst;
5143 return Match_Success;
5144 case Mips::LWP_MM:
5145 case Mips::LWP_MMR6:
5146 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5147 return Match_RequiresDifferentSrcAndDst;
5148 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005149 case Mips::SYNC:
5150 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5151 return Match_NonZeroOperandForSync;
5152 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005153 // As described the MIPSR6 spec, the compact branches that compare registers
5154 // must:
5155 // a) Not use the zero register.
5156 // b) Not use the same register twice.
5157 // c) rs < rt for bnec, beqc.
5158 // NB: For this case, the encoding will swap the operands as their
5159 // ordering doesn't matter. GAS performs this transformation too.
5160 // Hence, that constraint does not have to be enforced.
5161 //
5162 // The compact branches that branch iff the signed addition of two registers
5163 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5164 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005165 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5166 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5167 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5168 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5169 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5170 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005171 case Mips::BLEZC64:
5172 case Mips::BGEZC64:
5173 case Mips::BGTZC64:
5174 case Mips::BLTZC64:
5175 case Mips::BEQZC64:
5176 case Mips::BNEZC64:
5177 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5178 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005179 return Match_RequiresNoZeroRegister;
5180 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005181 case Mips::BGEC: case Mips::BGEC_MMR6:
5182 case Mips::BLTC: case Mips::BLTC_MMR6:
5183 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5184 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5185 case Mips::BEQC: case Mips::BEQC_MMR6:
5186 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005187 case Mips::BGEC64:
5188 case Mips::BLTC64:
5189 case Mips::BGEUC64:
5190 case Mips::BLTUC64:
5191 case Mips::BEQC64:
5192 case Mips::BNEC64:
5193 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5194 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005195 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005196 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5197 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005198 return Match_RequiresNoZeroRegister;
5199 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5200 return Match_RequiresDifferentOperands;
5201 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005202 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005203 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5204 "Operands must be immediates for dins!");
5205 const signed Pos = Inst.getOperand(2).getImm();
5206 const signed Size = Inst.getOperand(3).getImm();
5207 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5208 return Match_RequiresPosSizeRange0_32;
5209 return Match_Success;
5210 }
5211 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005212 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005213 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5214 "Operands must be immediates for dinsm/dinsu!");
5215 const signed Pos = Inst.getOperand(2).getImm();
5216 const signed Size = Inst.getOperand(3).getImm();
5217 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5218 return Match_RequiresPosSizeRange33_64;
5219 return Match_Success;
5220 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005221 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005222 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5223 "Operands must be immediates for DEXTM!");
5224 const signed Pos = Inst.getOperand(2).getImm();
5225 const signed Size = Inst.getOperand(3).getImm();
5226 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5227 return Match_RequiresPosSizeUImm6;
5228 return Match_Success;
5229 }
5230 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005231 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005232 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5233 "Operands must be immediates for dextm/dextu!");
5234 const signed Pos = Inst.getOperand(2).getImm();
5235 const signed Size = Inst.getOperand(3).getImm();
5236 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5237 return Match_RequiresPosSizeRange33_64;
5238 return Match_Success;
5239 }
Simon Dardisb60833c2016-05-31 17:34:42 +00005240 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005241
5242 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5243 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5244 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5245 return Match_NoFCCRegisterForCurrentISA;
5246
5247 return Match_Success;
5248
Matheus Almeida595fcab2014-06-11 15:05:56 +00005249}
5250
Daniel Sanders52da7af2015-11-06 12:11:03 +00005251static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5252 uint64_t ErrorInfo) {
5253 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5254 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5255 if (ErrorLoc == SMLoc())
5256 return Loc;
5257 return ErrorLoc;
5258 }
5259 return Loc;
5260}
5261
David Blaikie960ea3f2014-06-08 16:18:35 +00005262bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5263 OperandVector &Operands,
5264 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005265 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005266 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005267 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005268 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005269 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005270
5271 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005272 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005273 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005274 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005275 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005276 case Match_MissingFeature:
5277 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5278 return true;
5279 case Match_InvalidOperand: {
5280 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005281 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005282 if (ErrorInfo >= Operands.size())
5283 return Error(IDLoc, "too few operands for instruction");
5284
Daniel Sanders52da7af2015-11-06 12:11:03 +00005285 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005286 if (ErrorLoc == SMLoc())
5287 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005288 }
5289
5290 return Error(ErrorLoc, "invalid operand for instruction");
5291 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005292 case Match_NonZeroOperandForSync:
5293 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005294 case Match_MnemonicFail:
5295 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005296 case Match_RequiresDifferentSrcAndDst:
5297 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005298 case Match_RequiresDifferentOperands:
5299 return Error(IDLoc, "registers must be different");
5300 case Match_RequiresNoZeroRegister:
5301 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005302 case Match_RequiresSameSrcAndDst:
5303 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005304 case Match_NoFCCRegisterForCurrentISA:
5305 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5306 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005307 case Match_Immz:
5308 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005309 case Match_UImm1_0:
5310 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5311 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005312 case Match_UImm2_0:
5313 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5314 "expected 2-bit unsigned immediate");
5315 case Match_UImm2_1:
5316 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5317 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005318 case Match_UImm3_0:
5319 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5320 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005321 case Match_UImm4_0:
5322 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5323 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005324 case Match_SImm4_0:
5325 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5326 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005327 case Match_UImm5_0:
5328 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5329 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005330 case Match_SImm5_0:
5331 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5332 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005333 case Match_UImm5_1:
5334 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5335 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005336 case Match_UImm5_32:
5337 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5338 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005339 case Match_UImm5_33:
5340 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5341 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005342 case Match_UImm5_0_Report_UImm6:
5343 // This is used on UImm5 operands that have a corresponding UImm5_32
5344 // operand to avoid confusing the user.
5345 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5346 "expected 6-bit unsigned immediate");
5347 case Match_UImm5_Lsl2:
5348 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5349 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005350 case Match_UImmRange2_64:
5351 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5352 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005353 case Match_UImm6_0:
5354 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5355 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005356 case Match_UImm6_Lsl2:
5357 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5358 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005359 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005360 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5361 "expected 6-bit signed immediate");
5362 case Match_UImm7_0:
5363 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5364 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005365 case Match_UImm7_N1:
5366 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5367 "expected immediate in range -1 .. 126");
5368 case Match_SImm7_Lsl2:
5369 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5370 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005371 case Match_UImm8_0:
5372 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5373 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005374 case Match_UImm10_0:
5375 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5376 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005377 case Match_SImm10_0:
5378 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5379 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005380 case Match_SImm11_0:
5381 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5382 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005383 case Match_UImm16:
5384 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005385 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005386 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5387 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005388 case Match_SImm16:
5389 case Match_SImm16_Relaxed:
5390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5391 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005392 case Match_SImm19_Lsl2:
5393 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5394 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005395 case Match_UImm20_0:
5396 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5397 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005398 case Match_UImm26_0:
5399 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5400 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005401 case Match_SImm32:
5402 case Match_SImm32_Relaxed:
5403 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5404 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005405 case Match_UImm32_Coerced:
5406 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5407 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005408 case Match_MemSImm9:
5409 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5410 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005411 case Match_MemSImm10:
5412 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5413 "expected memory with 10-bit signed offset");
5414 case Match_MemSImm10Lsl1:
5415 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5416 "expected memory with 11-bit signed offset and multiple of 2");
5417 case Match_MemSImm10Lsl2:
5418 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5419 "expected memory with 12-bit signed offset and multiple of 4");
5420 case Match_MemSImm10Lsl3:
5421 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5422 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005423 case Match_MemSImm11:
5424 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5425 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005426 case Match_MemSImm12:
5427 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5428 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005429 case Match_MemSImm16:
5430 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5431 "expected memory with 16-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005432 case Match_RequiresPosSizeRange0_32: {
5433 SMLoc ErrorStart = Operands[3]->getStartLoc();
5434 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5435 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5436 SMRange(ErrorStart, ErrorEnd));
5437 }
Simon Dardis55e44672017-09-14 17:27:53 +00005438 case Match_RequiresPosSizeUImm6: {
5439 SMLoc ErrorStart = Operands[3]->getStartLoc();
5440 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5441 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5442 SMRange(ErrorStart, ErrorEnd));
5443 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005444 case Match_RequiresPosSizeRange33_64: {
5445 SMLoc ErrorStart = Operands[3]->getStartLoc();
5446 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5447 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5448 SMRange(ErrorStart, ErrorEnd));
5449 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005450 }
Craig Topper589ceee2015-01-03 08:16:34 +00005451
5452 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005453}
5454
Toma Tabacud9d344b2015-04-27 14:05:04 +00005455void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5456 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5457 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5458 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005459}
5460
Toma Tabacu81496c12015-05-20 08:54:45 +00005461void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5462 if (!AssemblerOptions.back()->isMacro())
5463 Warning(Loc, "macro instruction expanded into multiple instructions");
5464}
5465
Daniel Sandersef638fe2014-10-03 15:37:37 +00005466void
5467MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5468 SMRange Range, bool ShowColors) {
5469 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005470 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005471 ShowColors);
5472}
5473
Jack Carter1ac53222013-02-20 23:11:17 +00005474int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005475 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005476
Vladimir Medic4c299852013-11-06 11:27:05 +00005477 CC = StringSwitch<unsigned>(Name)
5478 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005479 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005480 .Case("a0", 4)
5481 .Case("a1", 5)
5482 .Case("a2", 6)
5483 .Case("a3", 7)
5484 .Case("v0", 2)
5485 .Case("v1", 3)
5486 .Case("s0", 16)
5487 .Case("s1", 17)
5488 .Case("s2", 18)
5489 .Case("s3", 19)
5490 .Case("s4", 20)
5491 .Case("s5", 21)
5492 .Case("s6", 22)
5493 .Case("s7", 23)
5494 .Case("k0", 26)
5495 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005496 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005497 .Case("sp", 29)
5498 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005499 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005500 .Case("ra", 31)
5501 .Case("t0", 8)
5502 .Case("t1", 9)
5503 .Case("t2", 10)
5504 .Case("t3", 11)
5505 .Case("t4", 12)
5506 .Case("t5", 13)
5507 .Case("t6", 14)
5508 .Case("t7", 15)
5509 .Case("t8", 24)
5510 .Case("t9", 25)
5511 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005512
Toma Tabacufda445c2014-09-15 15:33:01 +00005513 if (!(isABI_N32() || isABI_N64()))
5514 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005515
Daniel Sandersef638fe2014-10-03 15:37:37 +00005516 if (12 <= CC && CC <= 15) {
5517 // Name is one of t4-t7
5518 AsmToken RegTok = getLexer().peekTok();
5519 SMRange RegRange = RegTok.getLocRange();
5520
5521 StringRef FixedName = StringSwitch<StringRef>(Name)
5522 .Case("t4", "t0")
5523 .Case("t5", "t1")
5524 .Case("t6", "t2")
5525 .Case("t7", "t3")
5526 .Default("");
5527 assert(FixedName != "" && "Register name is not one of t4-t7.");
5528
5529 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5530 "Did you mean $" + FixedName + "?", RegRange);
5531 }
5532
Toma Tabacufda445c2014-09-15 15:33:01 +00005533 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5534 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5535 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5536 if (8 <= CC && CC <= 11)
5537 CC += 4;
5538
5539 if (CC == -1)
5540 CC = StringSwitch<unsigned>(Name)
5541 .Case("a4", 8)
5542 .Case("a5", 9)
5543 .Case("a6", 10)
5544 .Case("a7", 11)
5545 .Case("kt0", 26)
5546 .Case("kt1", 27)
5547 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005548
5549 return CC;
5550}
Jack Carterd0bd6422013-04-18 00:41:53 +00005551
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005552int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5553 int CC;
5554
5555 CC = StringSwitch<unsigned>(Name)
5556 .Case("hwr_cpunum", 0)
5557 .Case("hwr_synci_step", 1)
5558 .Case("hwr_cc", 2)
5559 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005560 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005561 .Default(-1);
5562
5563 return CC;
5564}
5565
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005566int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005567 if (Name[0] == 'f') {
5568 StringRef NumString = Name.substr(1);
5569 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005570 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005571 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005572 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005573 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005574 return IntVal;
5575 }
5576 return -1;
5577}
Jack Cartera63b16a2012-09-07 00:23:42 +00005578
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005579int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005580 if (Name.startswith("fcc")) {
5581 StringRef NumString = Name.substr(3);
5582 unsigned IntVal;
5583 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005584 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005585 if (IntVal > 7) // There are only 8 fcc registers.
5586 return -1;
5587 return IntVal;
5588 }
5589 return -1;
5590}
5591
5592int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005593 if (Name.startswith("ac")) {
5594 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005595 unsigned IntVal;
5596 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005597 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005598 if (IntVal > 3) // There are only 3 acc registers.
5599 return -1;
5600 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005601 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005602 return -1;
5603}
Jack Carterd0bd6422013-04-18 00:41:53 +00005604
Jack Carter5dc8ac92013-09-25 23:50:44 +00005605int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5606 unsigned IntVal;
5607
5608 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5609 return -1;
5610
5611 if (IntVal > 31)
5612 return -1;
5613
5614 return IntVal;
5615}
5616
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005617int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5618 int CC;
5619
5620 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005621 .Case("msair", 0)
5622 .Case("msacsr", 1)
5623 .Case("msaaccess", 2)
5624 .Case("msasave", 3)
5625 .Case("msamodify", 4)
5626 .Case("msarequest", 5)
5627 .Case("msamap", 6)
5628 .Case("msaunmap", 7)
5629 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005630
5631 return CC;
5632}
5633
Simon Dardis3aa8a902017-02-06 12:43:46 +00005634bool MipsAsmParser::canUseATReg() {
5635 return AssemblerOptions.back()->getATRegIndex() != 0;
5636}
5637
Toma Tabacu89a712b2015-04-15 10:48:56 +00005638unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005639 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005640 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005641 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005642 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005643 return 0;
5644 }
5645 unsigned AT = getReg(
5646 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005647 return AT;
5648}
Jack Carter0b744b32012-10-04 02:29:46 +00005649
Jack Carterd0bd6422013-04-18 00:41:53 +00005650unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005651 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005652}
5653
Toma Tabacu13964452014-09-04 13:23:44 +00005654bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005655 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005656 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005657
Jack Carter30a59822012-10-04 04:03:53 +00005658 // Check if the current operand has a custom associated parser, if so, try to
5659 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005660 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5661 if (ResTy == MatchOperand_Success)
5662 return false;
5663 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5664 // there was a match, but an error occurred, in which case, just return that
5665 // the operand parsing failed.
5666 if (ResTy == MatchOperand_ParseFail)
5667 return true;
5668
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005669 DEBUG(dbgs() << ".. Generic Parser\n");
5670
Jack Carterb4dbc172012-09-05 23:34:03 +00005671 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005672 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005673 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005674 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005675
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005676 // Almost all registers have been parsed by custom parsers. There is only
5677 // one exception to this. $zero (and it's alias $0) will reach this point
5678 // for div, divu, and similar instructions because it is not an operand
5679 // to the instruction definition but an explicit register. Special case
5680 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005681 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005682 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005683
Jack Carterd0bd6422013-04-18 00:41:53 +00005684 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005685 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005686 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005687 return true;
5688
Jack Carter873c7242013-01-12 01:03:14 +00005689 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005690 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005691 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005692 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005693 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005694
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005695 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005696 return false;
5697 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005698 default: {
5699 DEBUG(dbgs() << ".. generic integer expression\n");
5700
5701 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005702 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005703 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005704 return true;
5705
Jack Carter873c7242013-01-12 01:03:14 +00005706 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5707
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005708 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005709 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005710 }
Jack Carter0b744b32012-10-04 02:29:46 +00005711 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005712 return true;
5713}
5714
Jack Carterb5cf5902013-04-17 00:18:04 +00005715bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005716 switch (Expr->getKind()) {
5717 case MCExpr::Constant:
5718 return true;
5719 case MCExpr::SymbolRef:
5720 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005721 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005722 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005723 if (!isEvaluated(BE->getLHS()))
5724 return false;
5725 return isEvaluated(BE->getRHS());
5726 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005727 case MCExpr::Unary:
5728 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005729 case MCExpr::Target:
5730 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005731 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005732 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005733}
Jack Carterd0bd6422013-04-18 00:41:53 +00005734
Jack Carterb4dbc172012-09-05 23:34:03 +00005735bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5736 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005737 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005738 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005739 if (ResTy == MatchOperand_Success) {
5740 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005741 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005742 StartLoc = Operand.getStartLoc();
5743 EndLoc = Operand.getEndLoc();
5744
5745 // AFAIK, we only support numeric registers and named GPR's in CFI
5746 // directives.
5747 // Don't worry about eating tokens before failing. Using an unrecognised
5748 // register is a parse error.
5749 if (Operand.isGPRAsmReg()) {
5750 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005751 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005752 }
5753
5754 return (RegNo == (unsigned)-1);
5755 }
5756
5757 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005758 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005759}
5760
Jack Carterb5cf5902013-04-17 00:18:04 +00005761bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005762 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005763
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005764 if (isParenExpr)
5765 return getParser().parseParenExprOfDepth(0, Res, S);
5766 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005767}
5768
Alex Bradbury58eba092016-11-01 16:32:05 +00005769OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005770MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005771 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005772 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005773 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005774 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005775 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005776 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005777 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005778 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005779
Jack Carterb5cf5902013-04-17 00:18:04 +00005780 if (getLexer().getKind() == AsmToken::LParen) {
5781 Parser.Lex();
5782 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005783 }
5784
Jack Carterb5cf5902013-04-17 00:18:04 +00005785 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005786 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005787 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005788
Jack Carterd0bd6422013-04-18 00:41:53 +00005789 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005790 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005791 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005792 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005793 SMLoc E =
5794 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005795 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005796 return MatchOperand_Success;
5797 }
5798 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005799 SMLoc E =
5800 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005801
Jack Carterd0bd6422013-04-18 00:41:53 +00005802 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005803 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005804 auto Base = MipsOperand::createGPRReg(
5805 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005806 Operands.push_back(
5807 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005808 return MatchOperand_Success;
5809 }
Simon Dardis858915f2016-10-18 15:17:17 +00005810 MCBinaryExpr::Opcode Opcode;
5811 // GAS and LLVM treat comparison operators different. GAS will generate -1
5812 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5813 // highly unlikely to be found in a memory offset expression, we don't
5814 // handle them.
5815 switch (Tok.getKind()) {
5816 case AsmToken::Plus:
5817 Opcode = MCBinaryExpr::Add;
5818 Parser.Lex();
5819 break;
5820 case AsmToken::Minus:
5821 Opcode = MCBinaryExpr::Sub;
5822 Parser.Lex();
5823 break;
5824 case AsmToken::Star:
5825 Opcode = MCBinaryExpr::Mul;
5826 Parser.Lex();
5827 break;
5828 case AsmToken::Pipe:
5829 Opcode = MCBinaryExpr::Or;
5830 Parser.Lex();
5831 break;
5832 case AsmToken::Amp:
5833 Opcode = MCBinaryExpr::And;
5834 Parser.Lex();
5835 break;
5836 case AsmToken::LessLess:
5837 Opcode = MCBinaryExpr::Shl;
5838 Parser.Lex();
5839 break;
5840 case AsmToken::GreaterGreater:
5841 Opcode = MCBinaryExpr::LShr;
5842 Parser.Lex();
5843 break;
5844 case AsmToken::Caret:
5845 Opcode = MCBinaryExpr::Xor;
5846 Parser.Lex();
5847 break;
5848 case AsmToken::Slash:
5849 Opcode = MCBinaryExpr::Div;
5850 Parser.Lex();
5851 break;
5852 case AsmToken::Percent:
5853 Opcode = MCBinaryExpr::Mod;
5854 Parser.Lex();
5855 break;
5856 default:
5857 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5858 return MatchOperand_ParseFail;
5859 }
5860 const MCExpr * NextExpr;
5861 if (getParser().parseExpression(NextExpr))
5862 return MatchOperand_ParseFail;
5863 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005864 }
5865
Jack Carterd0bd6422013-04-18 00:41:53 +00005866 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005867 }
5868
Toma Tabacu13964452014-09-04 13:23:44 +00005869 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005870 if (Res != MatchOperand_Success)
5871 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005872
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005873 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005874 Error(Parser.getTok().getLoc(), "')' expected");
5875 return MatchOperand_ParseFail;
5876 }
5877
Jack Carter873c7242013-01-12 01:03:14 +00005878 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5879
Jack Carterd0bd6422013-04-18 00:41:53 +00005880 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005881
Craig Topper062a2ba2014-04-25 05:30:21 +00005882 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005883 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005884
Jack Carterd0bd6422013-04-18 00:41:53 +00005885 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005886 std::unique_ptr<MipsOperand> op(
5887 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005888 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005889 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005890 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005891 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005892 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5893 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005894 if (IdVal->evaluateAsAbsolute(Imm))
5895 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005896 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005897 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005898 getContext());
5899 }
5900
David Blaikie960ea3f2014-06-08 16:18:35 +00005901 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005902 return MatchOperand_Success;
5903}
5904
David Blaikie960ea3f2014-06-08 16:18:35 +00005905bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005906 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005907 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005908 if (Sym) {
5909 SMLoc S = Parser.getTok().getLoc();
5910 const MCExpr *Expr;
5911 if (Sym->isVariable())
5912 Expr = Sym->getVariableValue();
5913 else
5914 return false;
5915 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005916 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005917 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005918 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005919 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005920 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005921 if (ResTy == MatchOperand_Success) {
5922 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005923 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005924 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005925 llvm_unreachable("Should never ParseFail");
5926 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005927 }
Jack Carterd76b2372013-03-21 21:44:16 +00005928 }
5929 }
5930 return false;
5931}
Jack Carterd0bd6422013-04-18 00:41:53 +00005932
Alex Bradbury58eba092016-11-01 16:32:05 +00005933OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005934MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005935 StringRef Identifier,
5936 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005937 int Index = matchCPURegisterName(Identifier);
5938 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005939 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005940 Index, Identifier, getContext().getRegisterInfo(), S,
5941 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005942 return MatchOperand_Success;
5943 }
5944
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005945 Index = matchHWRegsRegisterName(Identifier);
5946 if (Index != -1) {
5947 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005948 Index, Identifier, getContext().getRegisterInfo(), S,
5949 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005950 return MatchOperand_Success;
5951 }
5952
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005953 Index = matchFPURegisterName(Identifier);
5954 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005955 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005956 Index, Identifier, getContext().getRegisterInfo(), S,
5957 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005958 return MatchOperand_Success;
5959 }
5960
5961 Index = matchFCCRegisterName(Identifier);
5962 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005963 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005964 Index, Identifier, getContext().getRegisterInfo(), S,
5965 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005966 return MatchOperand_Success;
5967 }
5968
5969 Index = matchACRegisterName(Identifier);
5970 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005971 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005972 Index, Identifier, getContext().getRegisterInfo(), S,
5973 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005974 return MatchOperand_Success;
5975 }
5976
5977 Index = matchMSA128RegisterName(Identifier);
5978 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005979 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005980 Index, Identifier, getContext().getRegisterInfo(), S,
5981 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005982 return MatchOperand_Success;
5983 }
5984
5985 Index = matchMSA128CtrlRegisterName(Identifier);
5986 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005987 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005988 Index, Identifier, getContext().getRegisterInfo(), S,
5989 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005990 return MatchOperand_Success;
5991 }
5992
5993 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005994}
5995
Alex Bradbury58eba092016-11-01 16:32:05 +00005996OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005997MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005998 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005999 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006000
6001 if (Token.is(AsmToken::Identifier)) {
6002 DEBUG(dbgs() << ".. identifier\n");
6003 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006004 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006005 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006006 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006007 } else if (Token.is(AsmToken::Integer)) {
6008 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00006009 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006010 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
6011 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006012 return MatchOperand_Success;
6013 }
6014
6015 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
6016
6017 return MatchOperand_NoMatch;
6018}
6019
Alex Bradbury58eba092016-11-01 16:32:05 +00006020OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006021MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006022 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006023 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006024
6025 auto Token = Parser.getTok();
6026
6027 SMLoc S = Token.getLoc();
6028
6029 if (Token.isNot(AsmToken::Dollar)) {
6030 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
6031 if (Token.is(AsmToken::Identifier)) {
6032 if (searchSymbolAlias(Operands))
6033 return MatchOperand_Success;
6034 }
6035 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
6036 return MatchOperand_NoMatch;
6037 }
6038 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006039
Toma Tabacu13964452014-09-04 13:23:44 +00006040 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006041 if (ResTy == MatchOperand_Success) {
6042 Parser.Lex(); // $
6043 Parser.Lex(); // identifier
6044 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006045 return ResTy;
6046}
6047
Alex Bradbury58eba092016-11-01 16:32:05 +00006048OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006049MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006050 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006051 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006052
6053 SMLoc S = getLexer().getLoc();
6054
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006055 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006056 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006057 if (ResTy != MatchOperand_NoMatch)
6058 return ResTy;
6059
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006060 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006061 const MCExpr *Expr = nullptr;
6062 if (Parser.parseExpression(Expr)) {
6063 // We have no way of knowing if a symbol was consumed so we must ParseFail
6064 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006065 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006066 Operands.push_back(
6067 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006068 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006069}
6070
Alex Bradbury58eba092016-11-01 16:32:05 +00006071OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006072MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006073 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006074 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006075 // If the first token is '$' we may have register operand. We have to reject
6076 // cases where it is not a register. Complicating the matter is that
6077 // register names are not reserved across all ABIs.
6078 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006079 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006080 if (Parser.getTok().is(AsmToken::Dollar)) {
6081 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6082 ? MatchOperand_ParseFail
6083 : MatchOperand_NoMatch;
6084 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006085 if (getParser().parseExpression(IdVal))
6086 return MatchOperand_ParseFail;
6087 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006088 if (!MCE)
6089 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006090 int64_t Val = MCE->getValue();
6091 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6092 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006093 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006094 return MatchOperand_Success;
6095}
6096
Alex Bradbury58eba092016-11-01 16:32:05 +00006097OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006098MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6099 MCAsmParser &Parser = getParser();
6100 SmallVector<unsigned, 10> Regs;
6101 unsigned RegNo;
6102 unsigned PrevReg = Mips::NoRegister;
6103 bool RegRange = false;
6104 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6105
6106 if (Parser.getTok().isNot(AsmToken::Dollar))
6107 return MatchOperand_ParseFail;
6108
6109 SMLoc S = Parser.getTok().getLoc();
6110 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6111 SMLoc E = getLexer().getLoc();
6112 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6113 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6114 if (RegRange) {
6115 // Remove last register operand because registers from register range
6116 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006117 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6118 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006119 Regs.push_back(RegNo);
6120 } else {
6121 unsigned TmpReg = PrevReg + 1;
6122 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006123 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6124 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6125 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006126 Error(E, "invalid register operand");
6127 return MatchOperand_ParseFail;
6128 }
6129
6130 PrevReg = TmpReg;
6131 Regs.push_back(TmpReg++);
6132 }
6133 }
6134
6135 RegRange = false;
6136 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006137 if ((PrevReg == Mips::NoRegister) &&
6138 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6139 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006140 Error(E, "$16 or $31 expected");
6141 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006142 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6143 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6144 !isGP64bit()) ||
6145 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6146 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6147 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006148 Error(E, "invalid register operand");
6149 return MatchOperand_ParseFail;
6150 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006151 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6152 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6153 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006154 Error(E, "consecutive register numbers expected");
6155 return MatchOperand_ParseFail;
6156 }
6157
6158 Regs.push_back(RegNo);
6159 }
6160
6161 if (Parser.getTok().is(AsmToken::Minus))
6162 RegRange = true;
6163
6164 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6165 !Parser.getTok().isNot(AsmToken::Comma)) {
6166 Error(E, "',' or '-' expected");
6167 return MatchOperand_ParseFail;
6168 }
6169
6170 Lex(); // Consume comma or minus
6171 if (Parser.getTok().isNot(AsmToken::Dollar))
6172 break;
6173
6174 PrevReg = RegNo;
6175 }
6176
6177 SMLoc E = Parser.getTok().getLoc();
6178 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6179 parseMemOperand(Operands);
6180 return MatchOperand_Success;
6181}
6182
Alex Bradbury58eba092016-11-01 16:32:05 +00006183OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006184MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6185 MCAsmParser &Parser = getParser();
6186
6187 SMLoc S = Parser.getTok().getLoc();
6188 if (parseAnyRegister(Operands) != MatchOperand_Success)
6189 return MatchOperand_ParseFail;
6190
6191 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006192 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006193
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006194 Operands.pop_back();
6195 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006196 return MatchOperand_Success;
6197}
6198
Alex Bradbury58eba092016-11-01 16:32:05 +00006199OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006200MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6201 MCAsmParser &Parser = getParser();
6202 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6203 SmallVector<unsigned, 10> Regs;
6204
6205 if (Parser.getTok().isNot(AsmToken::Dollar))
6206 return MatchOperand_ParseFail;
6207
6208 SMLoc S = Parser.getTok().getLoc();
6209
6210 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6211 return MatchOperand_ParseFail;
6212
6213 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6214 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6215 Regs.push_back(RegNo);
6216
6217 SMLoc E = Parser.getTok().getLoc();
6218 if (Parser.getTok().isNot(AsmToken::Comma)) {
6219 Error(E, "',' expected");
6220 return MatchOperand_ParseFail;
6221 }
6222
6223 // Remove comma.
6224 Parser.Lex();
6225
6226 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6227 return MatchOperand_ParseFail;
6228
6229 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6230 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6231 Regs.push_back(RegNo);
6232
6233 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6234
6235 return MatchOperand_Success;
6236}
6237
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006238/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6239/// either this.
6240/// ::= '(', register, ')'
6241/// handle it before we iterate so we don't get tripped up by the lack of
6242/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006243bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006244 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006245 if (getLexer().is(AsmToken::LParen)) {
6246 Operands.push_back(
6247 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6248 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006249 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006250 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006251 return Error(Loc, "unexpected token in argument list");
6252 }
6253 if (Parser.getTok().isNot(AsmToken::RParen)) {
6254 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006255 return Error(Loc, "unexpected token, expected ')'");
6256 }
6257 Operands.push_back(
6258 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6259 Parser.Lex();
6260 }
6261 return false;
6262}
6263
6264/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6265/// either one of these.
6266/// ::= '[', register, ']'
6267/// ::= '[', integer, ']'
6268/// handle it before we iterate so we don't get tripped up by the lack of
6269/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006270bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006271 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006272 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006273 if (getLexer().is(AsmToken::LBrac)) {
6274 Operands.push_back(
6275 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6276 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006277 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006278 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006279 return Error(Loc, "unexpected token in argument list");
6280 }
6281 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6282 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006283 return Error(Loc, "unexpected token, expected ']'");
6284 }
6285 Operands.push_back(
6286 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6287 Parser.Lex();
6288 }
6289 return false;
6290}
6291
David Blaikie960ea3f2014-06-08 16:18:35 +00006292bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6293 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006294 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006295 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006296
6297 // We have reached first instruction, module directive are now forbidden.
6298 getTargetStreamer().forbidModuleDirective();
6299
Vladimir Medic74593e62013-07-17 15:00:42 +00006300 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006301 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006302 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006303 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006304 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006305 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006306
6307 // Read the remaining operands.
6308 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6309 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006310 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006311 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006312 return Error(Loc, "unexpected token in argument list");
6313 }
Toma Tabacu13964452014-09-04 13:23:44 +00006314 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006315 return true;
6316 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006317
Jack Carterd0bd6422013-04-18 00:41:53 +00006318 while (getLexer().is(AsmToken::Comma)) {
6319 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006320 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006321 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006322 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006323 return Error(Loc, "unexpected token in argument list");
6324 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006325 // Parse bracket and parenthesis suffixes before we iterate
6326 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006327 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006328 return true;
6329 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006330 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006331 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006332 }
6333 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006334 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6335 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006336 return Error(Loc, "unexpected token in argument list");
6337 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006338 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006339 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006340}
6341
Nirav Dave996fc132016-05-05 14:15:46 +00006342// FIXME: Given that these have the same name, these should both be
6343// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006344bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006345 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006346 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006347}
6348
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006349bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006350 return Error(Loc, ErrorMsg);
6351}
6352
Jack Carter0b744b32012-10-04 02:29:46 +00006353bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006354 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006355 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006356
6357 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006358 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006359
6360 Parser.Lex(); // Eat "noat".
6361
Jack Carterd0bd6422013-04-18 00:41:53 +00006362 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006363 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006364 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006365 return false;
6366 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006367
6368 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006369 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006370 return false;
6371}
Jack Carterd0bd6422013-04-18 00:41:53 +00006372
Jack Carter0b744b32012-10-04 02:29:46 +00006373bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006374 // Line can be: ".set at", which sets $at to $1
6375 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006376 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006377 Parser.Lex(); // Eat "at".
6378
Jack Carter0b744b32012-10-04 02:29:46 +00006379 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006380 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006381 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006382
6383 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006384 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006385 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006386 }
6387
6388 if (getLexer().isNot(AsmToken::Equal)) {
6389 reportParseError("unexpected token, expected equals sign");
6390 return false;
6391 }
6392 Parser.Lex(); // Eat "=".
6393
6394 if (getLexer().isNot(AsmToken::Dollar)) {
6395 if (getLexer().is(AsmToken::EndOfStatement)) {
6396 reportParseError("no register specified");
6397 return false;
6398 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006399 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006400 return false;
6401 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006402 }
6403 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006404
Toma Tabacu16a74492015-02-13 10:30:57 +00006405 // Find out what "reg" is.
6406 unsigned AtRegNo;
6407 const AsmToken &Reg = Parser.getTok();
6408 if (Reg.is(AsmToken::Identifier)) {
6409 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6410 } else if (Reg.is(AsmToken::Integer)) {
6411 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006412 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006413 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006414 return false;
6415 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006416
6417 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006418 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006419 reportParseError("invalid register");
6420 return false;
6421 }
6422 Parser.Lex(); // Eat "reg".
6423
6424 // If this is not the end of the statement, report an error.
6425 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6426 reportParseError("unexpected token, expected end of statement");
6427 return false;
6428 }
6429
6430 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6431
6432 Parser.Lex(); // Consume the EndOfStatement.
6433 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006434}
6435
6436bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006437 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006438 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006439 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006441 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006442 return false;
6443 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006444 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006445 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006446 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006447 return false;
6448}
6449
6450bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006451 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006452 Parser.Lex();
6453 // If this is not the end of the statement, report an error.
6454 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006455 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006456 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006457 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006458 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006459 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006460 Parser.Lex(); // Consume the EndOfStatement.
6461 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006462}
6463
6464bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006465 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006466 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006467 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006468 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006469 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006470 return false;
6471 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006472 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006473 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006474 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006475 return false;
6476}
6477
6478bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006479 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006480 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006481 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006482 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006483 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006484 return false;
6485 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006486 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006487 reportParseError("`noreorder' must be set before `nomacro'");
6488 return false;
6489 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006490 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006491 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006492 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006493 return false;
6494}
Jack Carterd76b2372013-03-21 21:44:16 +00006495
Daniel Sanders44934432014-08-07 12:03:36 +00006496bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006497 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006498 Parser.Lex();
6499
6500 // If this is not the end of the statement, report an error.
6501 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006502 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006503
6504 setFeatureBits(Mips::FeatureMSA, "msa");
6505 getTargetStreamer().emitDirectiveSetMsa();
6506 return false;
6507}
6508
6509bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006510 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006511 Parser.Lex();
6512
6513 // If this is not the end of the statement, report an error.
6514 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006515 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006516
6517 clearFeatureBits(Mips::FeatureMSA, "msa");
6518 getTargetStreamer().emitDirectiveSetNoMsa();
6519 return false;
6520}
6521
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006522bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006523 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006524 Parser.Lex(); // Eat "nodsp".
6525
6526 // If this is not the end of the statement, report an error.
6527 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6528 reportParseError("unexpected token, expected end of statement");
6529 return false;
6530 }
6531
6532 clearFeatureBits(Mips::FeatureDSP, "dsp");
6533 getTargetStreamer().emitDirectiveSetNoDsp();
6534 return false;
6535}
6536
Toma Tabacucc2502d2014-11-04 17:18:07 +00006537bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006538 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006539 Parser.Lex(); // Eat "mips16".
6540
Jack Carter39536722014-01-22 23:08:42 +00006541 // If this is not the end of the statement, report an error.
6542 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006543 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006544 return false;
6545 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006546
6547 setFeatureBits(Mips::FeatureMips16, "mips16");
6548 getTargetStreamer().emitDirectiveSetMips16();
6549 Parser.Lex(); // Consume the EndOfStatement.
6550 return false;
6551}
6552
6553bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006554 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006555 Parser.Lex(); // Eat "nomips16".
6556
6557 // If this is not the end of the statement, report an error.
6558 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6559 reportParseError("unexpected token, expected end of statement");
6560 return false;
6561 }
6562
6563 clearFeatureBits(Mips::FeatureMips16, "mips16");
6564 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006565 Parser.Lex(); // Consume the EndOfStatement.
6566 return false;
6567}
6568
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006569bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006570 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006571 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006572 // Line can be: .set fp=32
6573 // .set fp=xx
6574 // .set fp=64
6575 Parser.Lex(); // Eat fp token
6576 AsmToken Tok = Parser.getTok();
6577 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006578 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006579 return false;
6580 }
6581 Parser.Lex(); // Eat '=' token.
6582 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006583
6584 if (!parseFpABIValue(FpAbiVal, ".set"))
6585 return false;
6586
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006587 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006588 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006589 return false;
6590 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006591 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006592 Parser.Lex(); // Consume the EndOfStatement.
6593 return false;
6594}
6595
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006596bool MipsAsmParser::parseSetOddSPRegDirective() {
6597 MCAsmParser &Parser = getParser();
6598
6599 Parser.Lex(); // Eat "oddspreg".
6600 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6601 reportParseError("unexpected token, expected end of statement");
6602 return false;
6603 }
6604
6605 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6606 getTargetStreamer().emitDirectiveSetOddSPReg();
6607 return false;
6608}
6609
6610bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6611 MCAsmParser &Parser = getParser();
6612
6613 Parser.Lex(); // Eat "nooddspreg".
6614 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6615 reportParseError("unexpected token, expected end of statement");
6616 return false;
6617 }
6618
6619 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6620 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6621 return false;
6622}
6623
Simon Dardis805f1e02017-07-11 21:28:36 +00006624bool MipsAsmParser::parseSetMtDirective() {
6625 MCAsmParser &Parser = getParser();
6626 Parser.Lex(); // Eat "mt".
6627
6628 // If this is not the end of the statement, report an error.
6629 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6630 reportParseError("unexpected token, expected end of statement");
6631 return false;
6632 }
6633
6634 setFeatureBits(Mips::FeatureMT, "mt");
6635 getTargetStreamer().emitDirectiveSetMt();
6636 Parser.Lex(); // Consume the EndOfStatement.
6637 return false;
6638}
6639
6640bool MipsAsmParser::parseSetNoMtDirective() {
6641 MCAsmParser &Parser = getParser();
6642 Parser.Lex(); // Eat "nomt".
6643
6644 // If this is not the end of the statement, report an error.
6645 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6646 reportParseError("unexpected token, expected end of statement");
6647 return false;
6648 }
6649
6650 clearFeatureBits(Mips::FeatureMT, "mt");
6651
6652 getTargetStreamer().emitDirectiveSetNoMt();
6653 Parser.Lex(); // Consume the EndOfStatement.
6654 return false;
6655}
6656
Toma Tabacu9db22db2014-09-09 10:15:38 +00006657bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006658 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006659 SMLoc Loc = getLexer().getLoc();
6660
6661 Parser.Lex();
6662 if (getLexer().isNot(AsmToken::EndOfStatement))
6663 return reportParseError("unexpected token, expected end of statement");
6664
6665 // Always keep an element on the options "stack" to prevent the user
6666 // from changing the initial options. This is how we remember them.
6667 if (AssemblerOptions.size() == 2)
6668 return reportParseError(Loc, ".set pop with no .set push");
6669
Akira Hatanakab11ef082015-11-14 06:35:56 +00006670 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006671 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006672 setAvailableFeatures(
6673 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6674 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006675
6676 getTargetStreamer().emitDirectiveSetPop();
6677 return false;
6678}
6679
6680bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006681 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006682 Parser.Lex();
6683 if (getLexer().isNot(AsmToken::EndOfStatement))
6684 return reportParseError("unexpected token, expected end of statement");
6685
6686 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006687 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006688 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006689
6690 getTargetStreamer().emitDirectiveSetPush();
6691 return false;
6692}
6693
Toma Tabacu29696502015-06-02 09:48:04 +00006694bool MipsAsmParser::parseSetSoftFloatDirective() {
6695 MCAsmParser &Parser = getParser();
6696 Parser.Lex();
6697 if (getLexer().isNot(AsmToken::EndOfStatement))
6698 return reportParseError("unexpected token, expected end of statement");
6699
6700 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6701 getTargetStreamer().emitDirectiveSetSoftFloat();
6702 return false;
6703}
6704
6705bool MipsAsmParser::parseSetHardFloatDirective() {
6706 MCAsmParser &Parser = getParser();
6707 Parser.Lex();
6708 if (getLexer().isNot(AsmToken::EndOfStatement))
6709 return reportParseError("unexpected token, expected end of statement");
6710
6711 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6712 getTargetStreamer().emitDirectiveSetHardFloat();
6713 return false;
6714}
6715
Jack Carterd76b2372013-03-21 21:44:16 +00006716bool MipsAsmParser::parseSetAssignment() {
6717 StringRef Name;
6718 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006719 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006720
6721 if (Parser.parseIdentifier(Name))
6722 reportParseError("expected identifier after .set");
6723
6724 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006725 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006726 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006727
Jack Carter3b2c96e2014-01-22 23:31:38 +00006728 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006729 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006730
Jim Grosbach6f482002015-05-18 18:43:14 +00006731 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006732 Sym->setVariableValue(Value);
6733
6734 return false;
6735}
Jack Carterd0bd6422013-04-18 00:41:53 +00006736
Toma Tabacu26647792014-09-09 12:52:14 +00006737bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006738 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006739 Parser.Lex();
6740 if (getLexer().isNot(AsmToken::EndOfStatement))
6741 return reportParseError("unexpected token, expected end of statement");
6742
6743 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006744 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006745 setAvailableFeatures(
6746 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6747 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006748 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6749
6750 getTargetStreamer().emitDirectiveSetMips0();
6751 return false;
6752}
6753
Toma Tabacu85618b32014-08-19 14:22:52 +00006754bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006755 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006756 Parser.Lex();
6757 if (getLexer().isNot(AsmToken::Equal))
6758 return reportParseError("unexpected token, expected equals sign");
6759
6760 Parser.Lex();
6761 StringRef Arch;
6762 if (Parser.parseIdentifier(Arch))
6763 return reportParseError("expected arch identifier");
6764
6765 StringRef ArchFeatureName =
6766 StringSwitch<StringRef>(Arch)
6767 .Case("mips1", "mips1")
6768 .Case("mips2", "mips2")
6769 .Case("mips3", "mips3")
6770 .Case("mips4", "mips4")
6771 .Case("mips5", "mips5")
6772 .Case("mips32", "mips32")
6773 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006774 .Case("mips32r3", "mips32r3")
6775 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006776 .Case("mips32r6", "mips32r6")
6777 .Case("mips64", "mips64")
6778 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006779 .Case("mips64r3", "mips64r3")
6780 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006781 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006782 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006783 .Case("r4000", "mips3") // This is an implementation of Mips3.
6784 .Default("");
6785
6786 if (ArchFeatureName.empty())
6787 return reportParseError("unsupported architecture");
6788
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006789 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6790 return reportParseError("mips64r6 does not support microMIPS");
6791
Toma Tabacu85618b32014-08-19 14:22:52 +00006792 selectArch(ArchFeatureName);
6793 getTargetStreamer().emitDirectiveSetArch(Arch);
6794 return false;
6795}
6796
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006797bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006798 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006799 Parser.Lex();
6800 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006801 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006802
Matheus Almeida2852af82014-04-22 10:15:54 +00006803 switch (Feature) {
6804 default:
6805 llvm_unreachable("Unimplemented feature");
6806 case Mips::FeatureDSP:
6807 setFeatureBits(Mips::FeatureDSP, "dsp");
6808 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006809 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006810 case Mips::FeatureDSPR2:
6811 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6812 getTargetStreamer().emitDirectiveSetDspr2();
6813 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006814 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006815 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006816 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006817 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006818 case Mips::FeatureMips1:
6819 selectArch("mips1");
6820 getTargetStreamer().emitDirectiveSetMips1();
6821 break;
6822 case Mips::FeatureMips2:
6823 selectArch("mips2");
6824 getTargetStreamer().emitDirectiveSetMips2();
6825 break;
6826 case Mips::FeatureMips3:
6827 selectArch("mips3");
6828 getTargetStreamer().emitDirectiveSetMips3();
6829 break;
6830 case Mips::FeatureMips4:
6831 selectArch("mips4");
6832 getTargetStreamer().emitDirectiveSetMips4();
6833 break;
6834 case Mips::FeatureMips5:
6835 selectArch("mips5");
6836 getTargetStreamer().emitDirectiveSetMips5();
6837 break;
6838 case Mips::FeatureMips32:
6839 selectArch("mips32");
6840 getTargetStreamer().emitDirectiveSetMips32();
6841 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006842 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006843 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006844 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006845 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006846 case Mips::FeatureMips32r3:
6847 selectArch("mips32r3");
6848 getTargetStreamer().emitDirectiveSetMips32R3();
6849 break;
6850 case Mips::FeatureMips32r5:
6851 selectArch("mips32r5");
6852 getTargetStreamer().emitDirectiveSetMips32R5();
6853 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006854 case Mips::FeatureMips32r6:
6855 selectArch("mips32r6");
6856 getTargetStreamer().emitDirectiveSetMips32R6();
6857 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006858 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006859 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006860 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006861 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006862 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006863 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006864 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006865 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006866 case Mips::FeatureMips64r3:
6867 selectArch("mips64r3");
6868 getTargetStreamer().emitDirectiveSetMips64R3();
6869 break;
6870 case Mips::FeatureMips64r5:
6871 selectArch("mips64r5");
6872 getTargetStreamer().emitDirectiveSetMips64R5();
6873 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006874 case Mips::FeatureMips64r6:
6875 selectArch("mips64r6");
6876 getTargetStreamer().emitDirectiveSetMips64R6();
6877 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006878 }
6879 return false;
6880}
6881
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006882bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006883 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006884 if (getLexer().isNot(AsmToken::Comma)) {
6885 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006886 return Error(Loc, ErrorStr);
6887 }
6888
Matheus Almeida2852af82014-04-22 10:15:54 +00006889 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006890 return true;
6891}
6892
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006893// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6894// In this class, it is only used for .cprestore.
6895// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6896// MipsTargetELFStreamer and MipsAsmParser.
6897bool MipsAsmParser::isPicAndNotNxxAbi() {
6898 return inPicMode() && !(isABI_N32() || isABI_N64());
6899}
6900
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006901bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006902 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006903 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006904
Toma Tabacudde4c462014-11-06 10:02:45 +00006905 if (inMips16Mode()) {
6906 reportParseError(".cpload is not supported in Mips16 mode");
6907 return false;
6908 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006909
David Blaikie960ea3f2014-06-08 16:18:35 +00006910 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006911 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006912 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6913 reportParseError("expected register containing function address");
6914 return false;
6915 }
6916
David Blaikie960ea3f2014-06-08 16:18:35 +00006917 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6918 if (!RegOpnd.isGPRAsmReg()) {
6919 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006920 return false;
6921 }
6922
Toma Tabacudde4c462014-11-06 10:02:45 +00006923 // If this is not the end of the statement, report an error.
6924 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6925 reportParseError("unexpected token, expected end of statement");
6926 return false;
6927 }
6928
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006929 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006930 return false;
6931}
6932
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006933bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6934 MCAsmParser &Parser = getParser();
6935
6936 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6937 // is used in non-PIC mode.
6938
6939 if (inMips16Mode()) {
6940 reportParseError(".cprestore is not supported in Mips16 mode");
6941 return false;
6942 }
6943
6944 // Get the stack offset value.
6945 const MCExpr *StackOffset;
6946 int64_t StackOffsetVal;
6947 if (Parser.parseExpression(StackOffset)) {
6948 reportParseError("expected stack offset value");
6949 return false;
6950 }
6951
6952 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6953 reportParseError("stack offset is not an absolute expression");
6954 return false;
6955 }
6956
6957 if (StackOffsetVal < 0) {
6958 Warning(Loc, ".cprestore with negative stack offset has no effect");
6959 IsCpRestoreSet = false;
6960 } else {
6961 IsCpRestoreSet = true;
6962 CpRestoreOffset = StackOffsetVal;
6963 }
6964
6965 // If this is not the end of the statement, report an error.
6966 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6967 reportParseError("unexpected token, expected end of statement");
6968 return false;
6969 }
6970
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006971 if (!getTargetStreamer().emitDirectiveCpRestore(
6972 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006973 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006974 Parser.Lex(); // Consume the EndOfStatement.
6975 return false;
6976}
6977
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006978bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006979 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006980 unsigned FuncReg;
6981 unsigned Save;
6982 bool SaveIsReg = true;
6983
Matheus Almeida7e815762014-06-18 13:08:59 +00006984 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006985 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006986 if (ResTy == MatchOperand_NoMatch) {
6987 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006988 return false;
6989 }
6990
6991 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6992 if (!FuncRegOpnd.isGPRAsmReg()) {
6993 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006994 return false;
6995 }
6996
6997 FuncReg = FuncRegOpnd.getGPR32Reg();
6998 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006999
Toma Tabacu65f10572014-09-16 15:00:52 +00007000 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007001 return true;
7002
Toma Tabacu13964452014-09-04 13:23:44 +00007003 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007004 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007005 const MCExpr *OffsetExpr;
7006 int64_t OffsetVal;
7007 SMLoc ExprLoc = getLexer().getLoc();
7008
7009 if (Parser.parseExpression(OffsetExpr) ||
7010 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7011 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007012 return false;
7013 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007014
7015 Save = OffsetVal;
7016 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007017 } else {
7018 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7019 if (!SaveOpnd.isGPRAsmReg()) {
7020 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007021 return false;
7022 }
7023 Save = SaveOpnd.getGPR32Reg();
7024 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007025
Toma Tabacu65f10572014-09-16 15:00:52 +00007026 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007027 return true;
7028
Toma Tabacu8874eac2015-02-18 13:46:53 +00007029 const MCExpr *Expr;
7030 if (Parser.parseExpression(Expr)) {
7031 reportParseError("expected expression");
7032 return false;
7033 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007034
Toma Tabacu8874eac2015-02-18 13:46:53 +00007035 if (Expr->getKind() != MCExpr::SymbolRef) {
7036 reportParseError("expected symbol");
7037 return false;
7038 }
7039 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7040
Daniel Sandersf173dda2015-09-22 10:50:09 +00007041 CpSaveLocation = Save;
7042 CpSaveLocationIsRegister = SaveIsReg;
7043
Toma Tabacu8874eac2015-02-18 13:46:53 +00007044 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7045 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007046 return false;
7047}
7048
Daniel Sandersf173dda2015-09-22 10:50:09 +00007049bool MipsAsmParser::parseDirectiveCPReturn() {
7050 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7051 CpSaveLocationIsRegister);
7052 return false;
7053}
7054
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007055bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007056 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007057 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7058 const AsmToken &Tok = Parser.getTok();
7059
7060 if (Tok.getString() == "2008") {
7061 Parser.Lex();
7062 getTargetStreamer().emitDirectiveNaN2008();
7063 return false;
7064 } else if (Tok.getString() == "legacy") {
7065 Parser.Lex();
7066 getTargetStreamer().emitDirectiveNaNLegacy();
7067 return false;
7068 }
7069 }
7070 // If we don't recognize the option passed to the .nan
7071 // directive (e.g. no option or unknown option), emit an error.
7072 reportParseError("invalid option in .nan directive");
7073 return false;
7074}
7075
Jack Carter0b744b32012-10-04 02:29:46 +00007076bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007077 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00007078 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00007079 const AsmToken &Tok = Parser.getTok();
7080
7081 if (Tok.getString() == "noat") {
7082 return parseSetNoAtDirective();
7083 } else if (Tok.getString() == "at") {
7084 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00007085 } else if (Tok.getString() == "arch") {
7086 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00007087 } else if (Tok.getString() == "bopt") {
7088 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
7089 getParser().Lex();
7090 return false;
7091 } else if (Tok.getString() == "nobopt") {
7092 // We're already running in nobopt mode, so nothing to do.
7093 getParser().Lex();
7094 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007095 } else if (Tok.getString() == "fp") {
7096 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007097 } else if (Tok.getString() == "oddspreg") {
7098 return parseSetOddSPRegDirective();
7099 } else if (Tok.getString() == "nooddspreg") {
7100 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00007101 } else if (Tok.getString() == "pop") {
7102 return parseSetPopDirective();
7103 } else if (Tok.getString() == "push") {
7104 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00007105 } else if (Tok.getString() == "reorder") {
7106 return parseSetReorderDirective();
7107 } else if (Tok.getString() == "noreorder") {
7108 return parseSetNoReorderDirective();
7109 } else if (Tok.getString() == "macro") {
7110 return parseSetMacroDirective();
7111 } else if (Tok.getString() == "nomacro") {
7112 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00007113 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00007114 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007115 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00007116 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007117 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007118 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007119 getTargetStreamer().emitDirectiveSetNoMicroMips();
7120 Parser.eatToEndOfStatement();
7121 return false;
7122 } else if (Tok.getString() == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007123 if (hasMips64r6()) {
7124 Error(Tok.getLoc(), ".set micromips directive is not supported with MIPS64R6");
7125 return false;
7126 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007127 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00007128 } else if (Tok.getString() == "mips0") {
7129 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00007130 } else if (Tok.getString() == "mips1") {
7131 return parseSetFeature(Mips::FeatureMips1);
7132 } else if (Tok.getString() == "mips2") {
7133 return parseSetFeature(Mips::FeatureMips2);
7134 } else if (Tok.getString() == "mips3") {
7135 return parseSetFeature(Mips::FeatureMips3);
7136 } else if (Tok.getString() == "mips4") {
7137 return parseSetFeature(Mips::FeatureMips4);
7138 } else if (Tok.getString() == "mips5") {
7139 return parseSetFeature(Mips::FeatureMips5);
7140 } else if (Tok.getString() == "mips32") {
7141 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00007142 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007143 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007144 } else if (Tok.getString() == "mips32r3") {
7145 return parseSetFeature(Mips::FeatureMips32r3);
7146 } else if (Tok.getString() == "mips32r5") {
7147 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007148 } else if (Tok.getString() == "mips32r6") {
7149 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007150 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007151 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007152 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007153 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007154 } else if (Tok.getString() == "mips64r3") {
7155 return parseSetFeature(Mips::FeatureMips64r3);
7156 } else if (Tok.getString() == "mips64r5") {
7157 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007158 } else if (Tok.getString() == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007159 if (inMicroMipsMode()) {
7160 Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS");
7161 return false;
7162 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007163 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00007164 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007165 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00007166 } else if (Tok.getString() == "dspr2") {
7167 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00007168 } else if (Tok.getString() == "nodsp") {
7169 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00007170 } else if (Tok.getString() == "msa") {
7171 return parseSetMsaDirective();
7172 } else if (Tok.getString() == "nomsa") {
7173 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00007174 } else if (Tok.getString() == "mt") {
7175 return parseSetMtDirective();
7176 } else if (Tok.getString() == "nomt") {
7177 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00007178 } else if (Tok.getString() == "softfloat") {
7179 return parseSetSoftFloatDirective();
7180 } else if (Tok.getString() == "hardfloat") {
7181 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00007182 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00007183 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00007184 parseSetAssignment();
7185 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00007186 }
Jack Carter07c818d2013-01-25 01:31:34 +00007187
Jack Carter0b744b32012-10-04 02:29:46 +00007188 return true;
7189}
7190
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007191/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007192/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007193bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007194 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007195 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007196 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007197 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007198 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007199 return true;
7200
7201 getParser().getStreamer().EmitValue(Value, Size);
7202
7203 if (getLexer().is(AsmToken::EndOfStatement))
7204 break;
7205
Jack Carter07c818d2013-01-25 01:31:34 +00007206 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007207 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007208 Parser.Lex();
7209 }
7210 }
7211
7212 Parser.Lex();
7213 return false;
7214}
7215
Vladimir Medic4c299852013-11-06 11:27:05 +00007216/// parseDirectiveGpWord
7217/// ::= .gpword local_sym
7218bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007219 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007220 const MCExpr *Value;
7221 // EmitGPRel32Value requires an expression, so we are using base class
7222 // method to evaluate the expression.
7223 if (getParser().parseExpression(Value))
7224 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007225 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007226
Vladimir Medice10c1122013-11-13 13:18:04 +00007227 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007228 return Error(getLexer().getLoc(),
7229 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007230 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007231 return false;
7232}
7233
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007234/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007235/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007236bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007237 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007238 const MCExpr *Value;
7239 // EmitGPRel64Value requires an expression, so we are using base class
7240 // method to evaluate the expression.
7241 if (getParser().parseExpression(Value))
7242 return true;
7243 getParser().getStreamer().EmitGPRel64Value(Value);
7244
7245 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007246 return Error(getLexer().getLoc(),
7247 "unexpected token, expected end of statement");
7248 Parser.Lex(); // Eat EndOfStatement token.
7249 return false;
7250}
7251
7252/// parseDirectiveDtpRelWord
7253/// ::= .dtprelword tls_sym
7254bool MipsAsmParser::parseDirectiveDtpRelWord() {
7255 MCAsmParser &Parser = getParser();
7256 const MCExpr *Value;
7257 // EmitDTPRel32Value requires an expression, so we are using base class
7258 // method to evaluate the expression.
7259 if (getParser().parseExpression(Value))
7260 return true;
7261 getParser().getStreamer().EmitDTPRel32Value(Value);
7262
7263 if (getLexer().isNot(AsmToken::EndOfStatement))
7264 return Error(getLexer().getLoc(),
7265 "unexpected token, expected end of statement");
7266 Parser.Lex(); // Eat EndOfStatement token.
7267 return false;
7268}
7269
7270/// parseDirectiveDtpRelDWord
7271/// ::= .dtpreldword tls_sym
7272bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7273 MCAsmParser &Parser = getParser();
7274 const MCExpr *Value;
7275 // EmitDTPRel64Value requires an expression, so we are using base class
7276 // method to evaluate the expression.
7277 if (getParser().parseExpression(Value))
7278 return true;
7279 getParser().getStreamer().EmitDTPRel64Value(Value);
7280
7281 if (getLexer().isNot(AsmToken::EndOfStatement))
7282 return Error(getLexer().getLoc(),
7283 "unexpected token, expected end of statement");
7284 Parser.Lex(); // Eat EndOfStatement token.
7285 return false;
7286}
7287
7288/// parseDirectiveTpRelWord
7289/// ::= .tprelword tls_sym
7290bool MipsAsmParser::parseDirectiveTpRelWord() {
7291 MCAsmParser &Parser = getParser();
7292 const MCExpr *Value;
7293 // EmitTPRel32Value requires an expression, so we are using base class
7294 // method to evaluate the expression.
7295 if (getParser().parseExpression(Value))
7296 return true;
7297 getParser().getStreamer().EmitTPRel32Value(Value);
7298
7299 if (getLexer().isNot(AsmToken::EndOfStatement))
7300 return Error(getLexer().getLoc(),
7301 "unexpected token, expected end of statement");
7302 Parser.Lex(); // Eat EndOfStatement token.
7303 return false;
7304}
7305
7306/// parseDirectiveTpRelDWord
7307/// ::= .tpreldword tls_sym
7308bool MipsAsmParser::parseDirectiveTpRelDWord() {
7309 MCAsmParser &Parser = getParser();
7310 const MCExpr *Value;
7311 // EmitTPRel64Value requires an expression, so we are using base class
7312 // method to evaluate the expression.
7313 if (getParser().parseExpression(Value))
7314 return true;
7315 getParser().getStreamer().EmitTPRel64Value(Value);
7316
7317 if (getLexer().isNot(AsmToken::EndOfStatement))
7318 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007319 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007320 Parser.Lex(); // Eat EndOfStatement token.
7321 return false;
7322}
7323
Jack Carter0cd3c192014-01-06 23:27:31 +00007324bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007325 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007326 // Get the option token.
7327 AsmToken Tok = Parser.getTok();
7328 // At the moment only identifiers are supported.
7329 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007330 return Error(Parser.getTok().getLoc(),
7331 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007332 }
7333
7334 StringRef Option = Tok.getIdentifier();
7335
7336 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007337 // MipsAsmParser needs to know if the current PIC mode changes.
7338 IsPicEnabled = false;
7339
Jack Carter0cd3c192014-01-06 23:27:31 +00007340 getTargetStreamer().emitDirectiveOptionPic0();
7341 Parser.Lex();
7342 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007343 return Error(Parser.getTok().getLoc(),
7344 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007345 }
7346 return false;
7347 }
7348
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007349 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007350 // MipsAsmParser needs to know if the current PIC mode changes.
7351 IsPicEnabled = true;
7352
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007353 getTargetStreamer().emitDirectiveOptionPic2();
7354 Parser.Lex();
7355 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007356 return Error(Parser.getTok().getLoc(),
7357 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007358 }
7359 return false;
7360 }
7361
Jack Carter0cd3c192014-01-06 23:27:31 +00007362 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007363 Warning(Parser.getTok().getLoc(),
7364 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007365 Parser.eatToEndOfStatement();
7366 return false;
7367}
7368
Toma Tabacu9ca50962015-04-16 09:53:47 +00007369/// parseInsnDirective
7370/// ::= .insn
7371bool MipsAsmParser::parseInsnDirective() {
7372 // If this is not the end of the statement, report an error.
7373 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7374 reportParseError("unexpected token, expected end of statement");
7375 return false;
7376 }
7377
7378 // The actual label marking happens in
7379 // MipsELFStreamer::createPendingLabelRelocs().
7380 getTargetStreamer().emitDirectiveInsn();
7381
7382 getParser().Lex(); // Eat EndOfStatement token.
7383 return false;
7384}
7385
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007386/// parseRSectionDirective
7387/// ::= .rdata
7388bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7389 // If this is not the end of the statement, report an error.
7390 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7391 reportParseError("unexpected token, expected end of statement");
7392 return false;
7393 }
7394
7395 MCSection *ELFSection = getContext().getELFSection(
7396 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7397 getParser().getStreamer().SwitchSection(ELFSection);
7398
7399 getParser().Lex(); // Eat EndOfStatement token.
7400 return false;
7401}
7402
Simon Atanasyanbe186202016-02-11 06:45:54 +00007403/// parseSSectionDirective
7404/// ::= .sbss
7405/// ::= .sdata
7406bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7407 // If this is not the end of the statement, report an error.
7408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7409 reportParseError("unexpected token, expected end of statement");
7410 return false;
7411 }
7412
7413 MCSection *ELFSection = getContext().getELFSection(
7414 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7415 getParser().getStreamer().SwitchSection(ELFSection);
7416
7417 getParser().Lex(); // Eat EndOfStatement token.
7418 return false;
7419}
7420
Daniel Sanders7e527422014-07-10 13:38:23 +00007421/// parseDirectiveModule
7422/// ::= .module oddspreg
7423/// ::= .module nooddspreg
7424/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007425/// ::= .module softfloat
7426/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007427/// ::= .module mt
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007428bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007429 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007430 MCAsmLexer &Lexer = getLexer();
7431 SMLoc L = Lexer.getLoc();
7432
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007433 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007434 // TODO : get a better message.
7435 reportParseError(".module directive must appear before any code");
7436 return false;
7437 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007438
Toma Tabacuc405c822015-01-23 10:40:19 +00007439 StringRef Option;
7440 if (Parser.parseIdentifier(Option)) {
7441 reportParseError("expected .module option identifier");
7442 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007443 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007444
Toma Tabacuc405c822015-01-23 10:40:19 +00007445 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007446 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007447
Toma Tabacu3c499582015-06-25 10:56:57 +00007448 // Synchronize the abiflags information with the FeatureBits information we
7449 // changed above.
7450 getTargetStreamer().updateABIInfo(*this);
7451
7452 // If printing assembly, use the recently updated abiflags information.
7453 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7454 // emitted at the end).
7455 getTargetStreamer().emitDirectiveModuleOddSPReg();
7456
Toma Tabacuc405c822015-01-23 10:40:19 +00007457 // If this is not the end of the statement, report an error.
7458 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7459 reportParseError("unexpected token, expected end of statement");
7460 return false;
7461 }
7462
7463 return false; // parseDirectiveModule has finished successfully.
7464 } else if (Option == "nooddspreg") {
7465 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007466 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007467 }
7468
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007469 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007470
Toma Tabacu3c499582015-06-25 10:56:57 +00007471 // Synchronize the abiflags information with the FeatureBits information we
7472 // changed above.
7473 getTargetStreamer().updateABIInfo(*this);
7474
7475 // If printing assembly, use the recently updated abiflags information.
7476 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7477 // emitted at the end).
7478 getTargetStreamer().emitDirectiveModuleOddSPReg();
7479
Toma Tabacuc405c822015-01-23 10:40:19 +00007480 // If this is not the end of the statement, report an error.
7481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7482 reportParseError("unexpected token, expected end of statement");
7483 return false;
7484 }
7485
7486 return false; // parseDirectiveModule has finished successfully.
7487 } else if (Option == "fp") {
7488 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007489 } else if (Option == "softfloat") {
7490 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7491
7492 // Synchronize the ABI Flags information with the FeatureBits information we
7493 // updated above.
7494 getTargetStreamer().updateABIInfo(*this);
7495
7496 // If printing assembly, use the recently updated ABI Flags information.
7497 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7498 // emitted later).
7499 getTargetStreamer().emitDirectiveModuleSoftFloat();
7500
7501 // If this is not the end of the statement, report an error.
7502 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7503 reportParseError("unexpected token, expected end of statement");
7504 return false;
7505 }
7506
7507 return false; // parseDirectiveModule has finished successfully.
7508 } else if (Option == "hardfloat") {
7509 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7510
7511 // Synchronize the ABI Flags information with the FeatureBits information we
7512 // updated above.
7513 getTargetStreamer().updateABIInfo(*this);
7514
7515 // If printing assembly, use the recently updated ABI Flags information.
7516 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7517 // emitted later).
7518 getTargetStreamer().emitDirectiveModuleHardFloat();
7519
7520 // If this is not the end of the statement, report an error.
7521 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7522 reportParseError("unexpected token, expected end of statement");
7523 return false;
7524 }
7525
7526 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007527 } else if (Option == "mt") {
7528 setModuleFeatureBits(Mips::FeatureMT, "mt");
7529
7530 // Synchronize the ABI Flags information with the FeatureBits information we
7531 // updated above.
7532 getTargetStreamer().updateABIInfo(*this);
7533
Simon Dardisd9611922017-07-11 21:36:58 +00007534 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007535 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7536 // emitted later).
7537 getTargetStreamer().emitDirectiveModuleMT();
7538
7539 // If this is not the end of the statement, report an error.
7540 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7541 reportParseError("unexpected token, expected end of statement");
7542 return false;
7543 }
7544
7545 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007546 } else {
7547 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7548 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007549}
7550
7551/// parseDirectiveModuleFP
7552/// ::= =32
7553/// ::= =xx
7554/// ::= =64
7555bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007556 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007557 MCAsmLexer &Lexer = getLexer();
7558
7559 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007560 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007561 return false;
7562 }
7563 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007564
Daniel Sanders7e527422014-07-10 13:38:23 +00007565 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007566 if (!parseFpABIValue(FpABI, ".module"))
7567 return false;
7568
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007569 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007570 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007571 return false;
7572 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007573
Toma Tabacua64e5402015-06-25 12:44:38 +00007574 // Synchronize the abiflags information with the FeatureBits information we
7575 // changed above.
7576 getTargetStreamer().updateABIInfo(*this);
7577
7578 // If printing assembly, use the recently updated abiflags information.
7579 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7580 // emitted at the end).
7581 getTargetStreamer().emitDirectiveModuleFP();
7582
Daniel Sanders7e527422014-07-10 13:38:23 +00007583 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007584 return false;
7585}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007586
Daniel Sanders7e527422014-07-10 13:38:23 +00007587bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007588 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007589 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007590 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007591 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007592
7593 if (Lexer.is(AsmToken::Identifier)) {
7594 StringRef Value = Parser.getTok().getString();
7595 Parser.Lex();
7596
7597 if (Value != "xx") {
7598 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7599 return false;
7600 }
7601
7602 if (!isABI_O32()) {
7603 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7604 return false;
7605 }
7606
Daniel Sanders7e527422014-07-10 13:38:23 +00007607 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007608 if (ModuleLevelOptions) {
7609 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7610 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7611 } else {
7612 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7613 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7614 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007615 return true;
7616 }
7617
7618 if (Lexer.is(AsmToken::Integer)) {
7619 unsigned Value = Parser.getTok().getIntVal();
7620 Parser.Lex();
7621
7622 if (Value != 32 && Value != 64) {
7623 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7624 return false;
7625 }
7626
7627 if (Value == 32) {
7628 if (!isABI_O32()) {
7629 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7630 return false;
7631 }
7632
Daniel Sanders7e527422014-07-10 13:38:23 +00007633 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007634 if (ModuleLevelOptions) {
7635 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7636 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7637 } else {
7638 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7639 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7640 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007641 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007642 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007643 if (ModuleLevelOptions) {
7644 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7645 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7646 } else {
7647 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7648 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7649 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007650 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007651
Daniel Sanders7e527422014-07-10 13:38:23 +00007652 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007653 }
7654
7655 return false;
7656}
7657
Jack Carter0b744b32012-10-04 02:29:46 +00007658bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007659 // This returns false if this function recognizes the directive
7660 // regardless of whether it is successfully handles or reports an
7661 // error. Otherwise it returns true to give the generic parser a
7662 // chance at recognizing it.
7663
Rafael Espindola961d4692014-11-11 05:18:41 +00007664 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007665 StringRef IDVal = DirectiveID.getString();
7666
Nirav Dave996fc132016-05-05 14:15:46 +00007667 if (IDVal == ".cpload") {
7668 parseDirectiveCpLoad(DirectiveID.getLoc());
7669 return false;
7670 }
7671 if (IDVal == ".cprestore") {
7672 parseDirectiveCpRestore(DirectiveID.getLoc());
7673 return false;
7674 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007675 if (IDVal == ".dword") {
7676 parseDataDirective(8, DirectiveID.getLoc());
7677 return false;
7678 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007679 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007680 StringRef SymbolName;
7681
7682 if (Parser.parseIdentifier(SymbolName)) {
7683 reportParseError("expected identifier after .ent");
7684 return false;
7685 }
7686
7687 // There's an undocumented extension that allows an integer to
7688 // follow the name of the procedure which AFAICS is ignored by GAS.
7689 // Example: .ent foo,2
7690 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7691 if (getLexer().isNot(AsmToken::Comma)) {
7692 // Even though we accept this undocumented extension for compatibility
7693 // reasons, the additional integer argument does not actually change
7694 // the behaviour of the '.ent' directive, so we would like to discourage
7695 // its use. We do this by not referring to the extended version in
7696 // error messages which are not directly related to its use.
7697 reportParseError("unexpected token, expected end of statement");
7698 return false;
7699 }
7700 Parser.Lex(); // Eat the comma.
7701 const MCExpr *DummyNumber;
7702 int64_t DummyNumberVal;
7703 // If the user was explicitly trying to use the extended version,
7704 // we still give helpful extension-related error messages.
7705 if (Parser.parseExpression(DummyNumber)) {
7706 reportParseError("expected number after comma");
7707 return false;
7708 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007709 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007710 reportParseError("expected an absolute expression after comma");
7711 return false;
7712 }
7713 }
7714
7715 // If this is not the end of the statement, report an error.
7716 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7717 reportParseError("unexpected token, expected end of statement");
7718 return false;
7719 }
7720
Jim Grosbach6f482002015-05-18 18:43:14 +00007721 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007722
7723 getTargetStreamer().emitDirectiveEnt(*Sym);
7724 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007725 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007726 return false;
7727 }
7728
Jack Carter07c818d2013-01-25 01:31:34 +00007729 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007730 StringRef SymbolName;
7731
7732 if (Parser.parseIdentifier(SymbolName)) {
7733 reportParseError("expected identifier after .end");
7734 return false;
7735 }
7736
7737 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7738 reportParseError("unexpected token, expected end of statement");
7739 return false;
7740 }
7741
7742 if (CurrentFn == nullptr) {
7743 reportParseError(".end used without .ent");
7744 return false;
7745 }
7746
7747 if ((SymbolName != CurrentFn->getName())) {
7748 reportParseError(".end symbol does not match .ent symbol");
7749 return false;
7750 }
7751
7752 getTargetStreamer().emitDirectiveEnd(SymbolName);
7753 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007754 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007755 return false;
7756 }
7757
Jack Carter07c818d2013-01-25 01:31:34 +00007758 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007759 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7760 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007761 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007762 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7763 reportParseError("expected stack register");
7764 return false;
7765 }
7766
7767 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7768 if (!StackRegOpnd.isGPRAsmReg()) {
7769 reportParseError(StackRegOpnd.getStartLoc(),
7770 "expected general purpose register");
7771 return false;
7772 }
7773 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7774
7775 if (Parser.getTok().is(AsmToken::Comma))
7776 Parser.Lex();
7777 else {
7778 reportParseError("unexpected token, expected comma");
7779 return false;
7780 }
7781
7782 // Parse the frame size.
7783 const MCExpr *FrameSize;
7784 int64_t FrameSizeVal;
7785
7786 if (Parser.parseExpression(FrameSize)) {
7787 reportParseError("expected frame size value");
7788 return false;
7789 }
7790
Jim Grosbach13760bd2015-05-30 01:25:56 +00007791 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007792 reportParseError("frame size not an absolute expression");
7793 return false;
7794 }
7795
7796 if (Parser.getTok().is(AsmToken::Comma))
7797 Parser.Lex();
7798 else {
7799 reportParseError("unexpected token, expected comma");
7800 return false;
7801 }
7802
7803 // Parse the return register.
7804 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007805 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007806 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7807 reportParseError("expected return register");
7808 return false;
7809 }
7810
7811 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7812 if (!ReturnRegOpnd.isGPRAsmReg()) {
7813 reportParseError(ReturnRegOpnd.getStartLoc(),
7814 "expected general purpose register");
7815 return false;
7816 }
7817
7818 // If this is not the end of the statement, report an error.
7819 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7820 reportParseError("unexpected token, expected end of statement");
7821 return false;
7822 }
7823
7824 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7825 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007826 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007827 return false;
7828 }
7829
Jack Carter07c818d2013-01-25 01:31:34 +00007830 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007831 parseDirectiveSet();
7832 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007833 }
7834
Daniel Sandersd97a6342014-08-13 10:07:34 +00007835 if (IDVal == ".mask" || IDVal == ".fmask") {
7836 // .mask bitmask, frame_offset
7837 // bitmask: One bit for each register used.
7838 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7839 // first register is expected to be saved.
7840 // Examples:
7841 // .mask 0x80000000, -4
7842 // .fmask 0x80000000, -4
7843 //
Jack Carterbe332172012-09-07 00:48:02 +00007844
Daniel Sandersd97a6342014-08-13 10:07:34 +00007845 // Parse the bitmask
7846 const MCExpr *BitMask;
7847 int64_t BitMaskVal;
7848
7849 if (Parser.parseExpression(BitMask)) {
7850 reportParseError("expected bitmask value");
7851 return false;
7852 }
7853
Jim Grosbach13760bd2015-05-30 01:25:56 +00007854 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007855 reportParseError("bitmask not an absolute expression");
7856 return false;
7857 }
7858
7859 if (Parser.getTok().is(AsmToken::Comma))
7860 Parser.Lex();
7861 else {
7862 reportParseError("unexpected token, expected comma");
7863 return false;
7864 }
7865
7866 // Parse the frame_offset
7867 const MCExpr *FrameOffset;
7868 int64_t FrameOffsetVal;
7869
7870 if (Parser.parseExpression(FrameOffset)) {
7871 reportParseError("expected frame offset value");
7872 return false;
7873 }
7874
Jim Grosbach13760bd2015-05-30 01:25:56 +00007875 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007876 reportParseError("frame offset not an absolute expression");
7877 return false;
7878 }
7879
7880 // If this is not the end of the statement, report an error.
7881 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7882 reportParseError("unexpected token, expected end of statement");
7883 return false;
7884 }
7885
7886 if (IDVal == ".mask")
7887 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7888 else
7889 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007890 return false;
7891 }
7892
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007893 if (IDVal == ".nan")
7894 return parseDirectiveNaN();
7895
Jack Carter07c818d2013-01-25 01:31:34 +00007896 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007897 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007898 return false;
7899 }
7900
Rafael Espindolab59fb732014-03-28 18:50:26 +00007901 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007902 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007903 return false;
7904 }
7905
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007906 if (IDVal == ".dtprelword") {
7907 parseDirectiveDtpRelWord();
7908 return false;
7909 }
7910
7911 if (IDVal == ".dtpreldword") {
7912 parseDirectiveDtpRelDWord();
7913 return false;
7914 }
7915
7916 if (IDVal == ".tprelword") {
7917 parseDirectiveTpRelWord();
7918 return false;
7919 }
7920
7921 if (IDVal == ".tpreldword") {
7922 parseDirectiveTpRelDWord();
7923 return false;
7924 }
7925
Jack Carter07c818d2013-01-25 01:31:34 +00007926 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007927 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007928 return false;
7929 }
7930
Scott Egertond1aeb052016-02-15 16:11:51 +00007931 if (IDVal == ".hword") {
7932 parseDataDirective(2, DirectiveID.getLoc());
7933 return false;
7934 }
7935
Nirav Dave996fc132016-05-05 14:15:46 +00007936 if (IDVal == ".option") {
7937 parseDirectiveOption();
7938 return false;
7939 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007940
7941 if (IDVal == ".abicalls") {
7942 getTargetStreamer().emitDirectiveAbiCalls();
7943 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007944 Error(Parser.getTok().getLoc(),
7945 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007946 }
7947 return false;
7948 }
7949
Nirav Dave996fc132016-05-05 14:15:46 +00007950 if (IDVal == ".cpsetup") {
7951 parseDirectiveCPSetup();
7952 return false;
7953 }
7954 if (IDVal == ".cpreturn") {
7955 parseDirectiveCPReturn();
7956 return false;
7957 }
7958 if (IDVal == ".module") {
7959 parseDirectiveModule();
7960 return false;
7961 }
7962 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7963 parseInternalDirectiveReallowModule();
7964 return false;
7965 }
7966 if (IDVal == ".insn") {
7967 parseInsnDirective();
7968 return false;
7969 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007970 if (IDVal == ".rdata") {
7971 parseRSectionDirective(".rodata");
7972 return false;
7973 }
Nirav Dave996fc132016-05-05 14:15:46 +00007974 if (IDVal == ".sbss") {
7975 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7976 return false;
7977 }
7978 if (IDVal == ".sdata") {
7979 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7980 return false;
7981 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007982
Rafael Espindola870c4e92012-01-11 03:56:41 +00007983 return true;
7984}
7985
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007986bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7987 // If this is not the end of the statement, report an error.
7988 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7989 reportParseError("unexpected token, expected end of statement");
7990 return false;
7991 }
7992
7993 getTargetStreamer().reallowModuleDirective();
7994
7995 getParser().Lex(); // Eat EndOfStatement token.
7996 return false;
7997}
7998
Rafael Espindola870c4e92012-01-11 03:56:41 +00007999extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008000 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8001 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8002 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8003 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008004}
Jack Carterb4dbc172012-09-05 23:34:03 +00008005
8006#define GET_REGISTER_MATCHER
8007#define GET_MATCHER_IMPLEMENTATION
8008#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008009
8010bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8011 // Find the appropriate table for this asm variant.
8012 const MatchEntry *Start, *End;
8013 switch (VariantID) {
8014 default: llvm_unreachable("invalid variant!");
8015 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8016 }
8017 // Search the table.
8018 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8019 return MnemonicRange.first != MnemonicRange.second;
8020}