blob: b3cfc869f294bffa4394494d0f838f15b58e5dec [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000307 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
308 const MCSubtargetInfo *STI);
309
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000310 bool reportParseError(Twine ErrorMsg);
311 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000312
Jack Carterb5cf5902013-04-17 00:18:04 +0000313 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000314
315 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000316 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000317 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000318 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000319 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000320 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000321 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000322 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000323 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000324 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000325 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000326 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000327 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000328 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000329 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000330
331 bool parseSetAtDirective();
332 bool parseSetNoAtDirective();
333 bool parseSetMacroDirective();
334 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000335 bool parseSetMsaDirective();
336 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000337 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000338 bool parseSetReorderDirective();
339 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000340 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000341 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000342 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000343 bool parseSetOddSPRegDirective();
344 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000345 bool parseSetPopDirective();
346 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000347 bool parseSetSoftFloatDirective();
348 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000349 bool parseSetMtDirective();
350 bool parseSetNoMtDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000351 bool parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000352 bool parseSetNoVirtDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000353
Jack Carterd76b2372013-03-21 21:44:16 +0000354 bool parseSetAssignment();
355
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000356 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000357 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000358 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000359 bool parseDirectiveDtpRelWord();
360 bool parseDirectiveDtpRelDWord();
361 bool parseDirectiveTpRelWord();
362 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000363 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000364 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000365 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
366 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000367
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000368 bool parseInternalDirectiveReallowModule();
369
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000370 bool eatComma(StringRef ErrorStr);
371
Jack Carter1ac53222013-02-20 23:11:17 +0000372 int matchCPURegisterName(StringRef Symbol);
373
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000374 int matchHWRegsRegisterName(StringRef Symbol);
375
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000376 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000377
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000378 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000379
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000380 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000381
Jack Carter5dc8ac92013-09-25 23:50:44 +0000382 int matchMSA128RegisterName(StringRef Name);
383
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000384 int matchMSA128CtrlRegisterName(StringRef Name);
385
Jack Carterd0bd6422013-04-18 00:41:53 +0000386 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000387
Toma Tabacu89a712b2015-04-15 10:48:56 +0000388 /// Returns the internal register number for the current AT. Also checks if
389 /// the current AT is unavailable (set to $0) and gives an error if it is.
390 /// This should be used in pseudo-instruction expansions which need AT.
391 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000392
Simon Dardis3aa8a902017-02-06 12:43:46 +0000393 bool canUseATReg();
394
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000395 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
396 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000397
398 // Helper function that checks if the value of a vector index is within the
399 // boundaries of accepted values for each RegisterKind
400 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
401 bool validateMSAIndex(int Val, int RegKind);
402
Daniel Sandersf0df2212014-08-04 12:20:00 +0000403 // Selects a new architecture by updating the FeatureBits with the necessary
404 // info including implied dependencies.
405 // Internally, it clears all the feature bits related to *any* architecture
406 // and selects the new one using the ToggleFeature functionality of the
407 // MCSubtargetInfo object that handles implied dependencies. The reason we
408 // clear all the arch related bits manually is because ToggleFeature only
409 // clears the features that imply the feature being cleared and not the
410 // features implied by the feature being cleared. This is easier to see
411 // with an example:
412 // --------------------------------------------------
413 // | Feature | Implies |
414 // | -------------------------------------------------|
415 // | FeatureMips1 | None |
416 // | FeatureMips2 | FeatureMips1 |
417 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
418 // | FeatureMips4 | FeatureMips3 |
419 // | ... | |
420 // --------------------------------------------------
421 //
422 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
423 // FeatureMipsGP64 | FeatureMips1)
424 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
425 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000426 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000427 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000428 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
429 STI.setFeatureBits(FeatureBits);
430 setAvailableFeatures(
431 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000432 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000433 }
434
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000435 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000436 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000437 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000438 setAvailableFeatures(
439 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000440 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000441 }
442 }
443
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000444 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000445 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000446 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000447 setAvailableFeatures(
448 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000449 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000450 }
451 }
452
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000453 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
454 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000456 }
457
458 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
459 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000460 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000461 }
462
Rafael Espindola870c4e92012-01-11 03:56:41 +0000463public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000464 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000465 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000466 Match_RequiresDifferentOperands,
467 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000468 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000469 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000470 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000471 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000472 Match_RequiresPosSizeRange0_32,
473 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000474 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000475#define GET_OPERAND_DIAGNOSTIC_TYPES
476#include "MipsGenAsmMatcher.inc"
477#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000478 };
479
Akira Hatanakab11ef082015-11-14 06:35:56 +0000480 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000481 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000482 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000483 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
484 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000485 MCAsmParserExtension::Initialize(parser);
486
Toma Tabacu11e14a92015-04-21 11:50:52 +0000487 parser.addAliasForDirective(".asciiz", ".asciz");
488
Jack Carterb4dbc172012-09-05 23:34:03 +0000489 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000491
Toma Tabacu9db22db2014-09-09 10:15:38 +0000492 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000493 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000494 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000495
Toma Tabacu9db22db2014-09-09 10:15:38 +0000496 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000497 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000499
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 getTargetStreamer().updateABIInfo(*this);
501
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000502 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000503 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000504
505 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000506
Rafael Espindola699281c2016-05-18 11:58:50 +0000507 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000508
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000509 IsCpRestoreSet = false;
510 CpRestoreOffset = -1;
511
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000512 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000513 if ((TheTriple.getArch() == Triple::mips) ||
514 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000515 IsLittleEndian = false;
516 else
517 IsLittleEndian = true;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000518
519 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
520 report_fatal_error("microMIPS64R6 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000521 }
522
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000523 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
524 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
525
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000526 bool isGP64bit() const {
527 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
528 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000529
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000530 bool isFP64bit() const {
531 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
532 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000533
Eric Christophera5762812015-01-26 17:33:46 +0000534 const MipsABIInfo &getABI() const { return ABI; }
535 bool isABI_N32() const { return ABI.IsN32(); }
536 bool isABI_N64() const { return ABI.IsN64(); }
537 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 bool isABI_FPXX() const {
539 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
540 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000541
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000542 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000543 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000544 }
545
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000546 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000547 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000549
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000550 bool hasMips1() const {
551 return getSTI().getFeatureBits()[Mips::FeatureMips1];
552 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000553
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000554 bool hasMips2() const {
555 return getSTI().getFeatureBits()[Mips::FeatureMips2];
556 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000557
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000558 bool hasMips3() const {
559 return getSTI().getFeatureBits()[Mips::FeatureMips3];
560 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000561
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000562 bool hasMips4() const {
563 return getSTI().getFeatureBits()[Mips::FeatureMips4];
564 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000565
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000566 bool hasMips5() const {
567 return getSTI().getFeatureBits()[Mips::FeatureMips5];
568 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000569
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000571 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000572 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000573
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000574 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000575 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000576 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000577
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000578 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000579 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000580 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000581
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000582 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000583 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000584 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000585
Daniel Sanders17793142015-02-18 16:24:50 +0000586 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000587 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000588 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000589
Daniel Sanders17793142015-02-18 16:24:50 +0000590 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000591 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000592 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000593
Daniel Sanders17793142015-02-18 16:24:50 +0000594 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000595 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000596 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000597
Daniel Sanders17793142015-02-18 16:24:50 +0000598 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000599 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000600 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000601
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000602 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000603 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000604 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000605
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000606 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000607 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000608 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000609
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000610 bool hasDSP() const {
611 return getSTI().getFeatureBits()[Mips::FeatureDSP];
612 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000613
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000614 bool hasDSPR2() const {
615 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
616 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000617
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000618 bool hasDSPR3() const {
619 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
620 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000621
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000622 bool hasMSA() const {
623 return getSTI().getFeatureBits()[Mips::FeatureMSA];
624 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000625
Kai Nackee0245392015-01-27 19:11:28 +0000626 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000627 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000628 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000629
Daniel Sandersa6994442015-08-18 12:33:54 +0000630 bool inPicMode() {
631 return IsPicEnabled;
632 }
633
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000634 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000635 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000636 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000637
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000638 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000639 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000640 }
641
Eric Christophere8ae3e32015-05-07 23:10:21 +0000642 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000643 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000644 }
Simon Dardisae719c52017-07-11 18:03:20 +0000645 bool hasMT() const {
646 return getSTI().getFeatureBits()[Mips::FeatureMT];
647 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000648
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000649 bool hasCRC() const {
650 return getSTI().getFeatureBits()[Mips::FeatureCRC];
651 }
652
Petar Jovanovicd4349f32018-04-27 09:12:08 +0000653 bool hasVirt() const {
654 return getSTI().getFeatureBits()[Mips::FeatureVirt];
655 }
656
Toma Tabacud9d344b2015-04-27 14:05:04 +0000657 /// Warn if RegIndex is the same as the current AT.
658 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000659
660 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000661
662 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000663
664 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
665 AsmToken::TokenKind OperatorToken,
666 MCContext &Ctx) override {
667 switch(OperatorToken) {
668 default:
669 llvm_unreachable("Unknown token");
670 return nullptr;
671 case AsmToken::PercentCall16:
672 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
673 case AsmToken::PercentCall_Hi:
674 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
675 case AsmToken::PercentCall_Lo:
676 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
677 case AsmToken::PercentDtprel_Hi:
678 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
679 case AsmToken::PercentDtprel_Lo:
680 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
681 case AsmToken::PercentGot:
682 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
683 case AsmToken::PercentGot_Disp:
684 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
685 case AsmToken::PercentGot_Hi:
686 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
687 case AsmToken::PercentGot_Lo:
688 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
689 case AsmToken::PercentGot_Ofst:
690 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
691 case AsmToken::PercentGot_Page:
692 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
693 case AsmToken::PercentGottprel:
694 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
695 case AsmToken::PercentGp_Rel:
696 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
697 case AsmToken::PercentHi:
698 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
699 case AsmToken::PercentHigher:
700 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
701 case AsmToken::PercentHighest:
702 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
703 case AsmToken::PercentLo:
704 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
705 case AsmToken::PercentNeg:
706 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
707 case AsmToken::PercentPcrel_Hi:
708 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
709 case AsmToken::PercentPcrel_Lo:
710 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
711 case AsmToken::PercentTlsgd:
712 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
713 case AsmToken::PercentTlsldm:
714 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
715 case AsmToken::PercentTprel_Hi:
716 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
717 case AsmToken::PercentTprel_Lo:
718 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
719 }
720 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000721};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000722
723/// MipsOperand - Instances of this class represent a parsed Mips machine
724/// instruction.
725class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000726public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 /// Broad categories of register classes
728 /// The exact class is finalized by the render method.
729 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000730 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000732 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000733 RegKind_FCC = 4, /// FCC
734 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
735 RegKind_MSACtrl = 16, /// MSA control registers
736 RegKind_COP2 = 32, /// COP2
737 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
738 /// context).
739 RegKind_CCR = 128, /// CCR
740 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000741 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000742 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 /// Potentially any (e.g. $1)
744 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
745 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000746 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000747 };
748
749private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000750 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000751 k_Immediate, /// An immediate (possibly involving symbol references)
752 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000753 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000754 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000755 k_RegList, /// A physical register list
756 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000757 } Kind;
758
David Blaikie960ea3f2014-06-08 16:18:35 +0000759public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 MipsOperand(KindTy K, MipsAsmParser &Parser)
761 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
762
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000763 ~MipsOperand() override {
764 switch (Kind) {
765 case k_Immediate:
766 break;
767 case k_Memory:
768 delete Mem.Base;
769 break;
770 case k_RegList:
771 delete RegList.List;
772 case k_RegisterIndex:
773 case k_Token:
774 case k_RegPair:
775 break;
776 }
777 }
778
David Blaikie960ea3f2014-06-08 16:18:35 +0000779private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 /// For diagnostics, and checking the assembler temporary
781 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000782
Eric Christopher8996c5d2013-03-15 00:42:55 +0000783 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000784 const char *Data;
785 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000786 };
787
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 struct RegIdxOp {
789 unsigned Index; /// Index into the register class
790 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000791 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000793 };
794
795 struct ImmOp {
796 const MCExpr *Val;
797 };
798
799 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000801 const MCExpr *Off;
802 };
803
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000804 struct RegListOp {
805 SmallVector<unsigned, 10> *List;
806 };
807
Jack Carterb4dbc172012-09-05 23:34:03 +0000808 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000809 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000811 struct ImmOp Imm;
812 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000813 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000814 };
815
816 SMLoc StartLoc, EndLoc;
817
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000819 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
820 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000821 const MCRegisterInfo *RegInfo,
822 SMLoc S, SMLoc E,
823 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000824 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 Op->RegIdx.Index = Index;
826 Op->RegIdx.RegInfo = RegInfo;
827 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000828 Op->RegIdx.Tok.Data = Str.data();
829 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 Op->StartLoc = S;
831 Op->EndLoc = E;
832 return Op;
833 }
834
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000835public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 /// Coerce the register to GPR32 and return the real register for the current
837 /// target.
838 unsigned getGPR32Reg() const {
839 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000840 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 unsigned ClassID = Mips::GPR32RegClassID;
842 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000843 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000844
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000845 /// Coerce the register to GPR32 and return the real register for the current
846 /// target.
847 unsigned getGPRMM16Reg() const {
848 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
849 unsigned ClassID = Mips::GPR32RegClassID;
850 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
851 }
852
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 /// Coerce the register to GPR64 and return the real register for the current
854 /// target.
855 unsigned getGPR64Reg() const {
856 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
857 unsigned ClassID = Mips::GPR64RegClassID;
858 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000859 }
860
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861private:
862 /// Coerce the register to AFGR64 and return the real register for the current
863 /// target.
864 unsigned getAFGR64Reg() const {
865 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
866 if (RegIdx.Index % 2 != 0)
867 AsmParser.Warning(StartLoc, "Float register should be even.");
868 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
869 .getRegister(RegIdx.Index / 2);
870 }
871
872 /// Coerce the register to FGR64 and return the real register for the current
873 /// target.
874 unsigned getFGR64Reg() const {
875 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
876 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
877 .getRegister(RegIdx.Index);
878 }
879
880 /// Coerce the register to FGR32 and return the real register for the current
881 /// target.
882 unsigned getFGR32Reg() const {
883 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
884 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
885 .getRegister(RegIdx.Index);
886 }
887
888 /// Coerce the register to FGRH32 and return the real register for the current
889 /// target.
890 unsigned getFGRH32Reg() const {
891 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
892 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
893 .getRegister(RegIdx.Index);
894 }
895
896 /// Coerce the register to FCC and return the real register for the current
897 /// target.
898 unsigned getFCCReg() const {
899 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
900 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
901 .getRegister(RegIdx.Index);
902 }
903
904 /// Coerce the register to MSA128 and return the real register for the current
905 /// target.
906 unsigned getMSA128Reg() const {
907 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
908 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
909 // identical
910 unsigned ClassID = Mips::MSA128BRegClassID;
911 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
912 }
913
914 /// Coerce the register to MSACtrl and return the real register for the
915 /// current target.
916 unsigned getMSACtrlReg() const {
917 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
918 unsigned ClassID = Mips::MSACtrlRegClassID;
919 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
920 }
921
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000922 /// Coerce the register to COP0 and return the real register for the
923 /// current target.
924 unsigned getCOP0Reg() const {
925 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
926 unsigned ClassID = Mips::COP0RegClassID;
927 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
928 }
929
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 /// Coerce the register to COP2 and return the real register for the
931 /// current target.
932 unsigned getCOP2Reg() const {
933 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
934 unsigned ClassID = Mips::COP2RegClassID;
935 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
936 }
937
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000938 /// Coerce the register to COP3 and return the real register for the
939 /// current target.
940 unsigned getCOP3Reg() const {
941 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
942 unsigned ClassID = Mips::COP3RegClassID;
943 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
944 }
945
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000946 /// Coerce the register to ACC64DSP and return the real register for the
947 /// current target.
948 unsigned getACC64DSPReg() const {
949 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
950 unsigned ClassID = Mips::ACC64DSPRegClassID;
951 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
952 }
953
954 /// Coerce the register to HI32DSP and return the real register for the
955 /// current target.
956 unsigned getHI32DSPReg() const {
957 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
958 unsigned ClassID = Mips::HI32DSPRegClassID;
959 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
960 }
961
962 /// Coerce the register to LO32DSP and return the real register for the
963 /// current target.
964 unsigned getLO32DSPReg() const {
965 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
966 unsigned ClassID = Mips::LO32DSPRegClassID;
967 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
968 }
969
970 /// Coerce the register to CCR and return the real register for the
971 /// current target.
972 unsigned getCCRReg() const {
973 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
974 unsigned ClassID = Mips::CCRRegClassID;
975 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
976 }
977
978 /// Coerce the register to HWRegs and return the real register for the
979 /// current target.
980 unsigned getHWRegsReg() const {
981 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
982 unsigned ClassID = Mips::HWRegsRegClassID;
983 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
984 }
985
986public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000987 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000988 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000989 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000990 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000991 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000992 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000993 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000994 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000995 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000996
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 void addRegOperands(MCInst &Inst, unsigned N) const {
998 llvm_unreachable("Use a custom parser instead");
999 }
1000
Daniel Sanders21bce302014-04-01 12:35:23 +00001001 /// Render the operand to an MCInst as a GPR32
1002 /// Asserts if the wrong number of operands are requested, or the operand
1003 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +00001004 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
1006 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1007 }
1008
1009 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
1011 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1012 }
1013
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001014 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001016 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001017 }
1018
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001019 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001021 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001022 }
1023
Jozef Kolek1904fa22014-11-24 14:25:53 +00001024 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001026 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001027 }
1028
Zoran Jovanovic41688672015-02-10 16:36:20 +00001029 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001031 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001032 }
1033
Daniel Sanders21bce302014-04-01 12:35:23 +00001034 /// Render the operand to an MCInst as a GPR64
1035 /// Asserts if the wrong number of operands are requested, or the operand
1036 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1038 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001039 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 }
1041
1042 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001044 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 }
1046
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001047 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
1049 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1050 }
1051
1052 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1053 assert(N == 1 && "Invalid number of operands!");
1054 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1055 }
1056
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1058 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001059 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 }
1061
1062 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001064 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001065 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001066 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001067 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001068 AsmParser.getParser().printError(
1069 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1070 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 }
1072
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001073 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1076 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1077 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1078 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1079 "registers");
1080 }
1081
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001082 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001084 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001085 }
1086
1087 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001089 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001090 }
1091
1092 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001094 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 }
1096
1097 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 }
1101
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001102 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
1104 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1105 }
1106
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001107 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001109 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 }
1111
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001112 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001114 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001115 }
1116
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001117 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001119 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001120 }
1121
1122 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1123 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001124 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001125 }
1126
1127 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001129 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 }
1131
1132 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001134 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 }
1136
1137 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1138 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001139 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 }
1141
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001142 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001143 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001145 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001146 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001147 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001148 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001149 Inst.addOperand(MCOperand::createImm(Imm));
1150 }
1151
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001152 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001153 void addSImmOperands(MCInst &Inst, unsigned N) const {
1154 if (isImm() && !isConstantImm()) {
1155 addExpr(Inst, getImm());
1156 return;
1157 }
1158 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1159 }
1160
1161 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001162 void addUImmOperands(MCInst &Inst, unsigned N) const {
1163 if (isImm() && !isConstantImm()) {
1164 addExpr(Inst, getImm());
1165 return;
1166 }
1167 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1168 }
1169
Daniel Sanders78e89022016-03-11 11:37:50 +00001170 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1171 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1172 assert(N == 1 && "Invalid number of operands!");
1173 int64_t Imm = getConstantImm() - Offset;
1174 Imm = SignExtend64<Bits>(Imm);
1175 Imm += Offset;
1176 Imm += AdjustOffset;
1177 Inst.addOperand(MCOperand::createImm(Imm));
1178 }
1179
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001180 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001181 assert(N == 1 && "Invalid number of operands!");
1182 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001184 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001185
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001186 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001187 assert(N == 2 && "Invalid number of operands!");
1188
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001189 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1190 ? getMemBase()->getGPR64Reg()
1191 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001192
1193 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001195 }
1196
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001197 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1198 assert(N == 2 && "Invalid number of operands!");
1199
Jim Grosbache9119e42015-05-13 18:37:00 +00001200 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001201
1202 const MCExpr *Expr = getMemOff();
1203 addExpr(Inst, Expr);
1204 }
1205
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001206 void addRegListOperands(MCInst &Inst, unsigned N) const {
1207 assert(N == 1 && "Invalid number of operands!");
1208
1209 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001210 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001211 }
1212
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001213 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001215 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001216 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001217 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1218 Inst.addOperand(MCOperand::createReg(
1219 RegIdx.RegInfo->getRegClass(
1220 AsmParser.getABI().AreGprs64bit()
1221 ? Mips::GPR64RegClassID
1222 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1223 Inst.addOperand(MCOperand::createReg(
1224 RegIdx.RegInfo->getRegClass(
1225 AsmParser.getABI().AreGprs64bit()
1226 ? Mips::GPR64RegClassID
1227 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001228 }
1229
Zoran Jovanovic41688672015-02-10 16:36:20 +00001230 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 2 && "Invalid number of operands!");
1232 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001233 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001234 }
1235
Craig Topper56c590a2014-04-29 07:58:02 +00001236 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001237 // As a special case until we sort out the definition of div/divu, accept
1238 // $0/$zero here so that MCK_ZERO works correctly.
1239 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001241
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001243 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001244
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001246 int64_t Res;
1247 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001249
Daniel Sanders52da7af2015-11-06 12:11:03 +00001250 bool isConstantImmz() const {
1251 return isConstantImm() && getConstantImm() == 0;
1252 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001253
Daniel Sandersea4f6532015-11-06 12:22:31 +00001254 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1255 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1256 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001257
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001258 template <unsigned Bits> bool isSImm() const {
1259 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1260 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001261
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001262 template <unsigned Bits> bool isUImm() const {
1263 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1264 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001265
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001266 template <unsigned Bits> bool isAnyImm() const {
1267 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1268 isUInt<Bits>(getConstantImm()))
1269 : isImm();
1270 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001271
Daniel Sanders78e89022016-03-11 11:37:50 +00001272 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1273 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001274 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001275
Hrvoje Varga46458d02016-02-25 12:53:29 +00001276 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1277 return isConstantImm() && getConstantImm() >= Bottom &&
1278 getConstantImm() <= Top;
1279 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001280
Craig Topper56c590a2014-04-29 07:58:02 +00001281 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 // Note: It's not possible to pretend that other operand kinds are tokens.
1283 // The matcher emitter checks tokens first.
1284 return Kind == k_Token;
1285 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001286
Craig Topper56c590a2014-04-29 07:58:02 +00001287 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001288
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001289 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001290 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001291 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001292
Simon Dardis4ccda502016-05-27 13:56:36 +00001293 // Allow relocation operators.
1294 // FIXME: This predicate and others need to look through binary expressions
1295 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001296 template <unsigned Bits, unsigned ShiftAmount = 0>
1297 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001298 if (!isMem())
1299 return false;
1300 if (!getMemBase()->isGPRAsmReg())
1301 return false;
1302 if (isa<MCTargetExpr>(getMemOff()) ||
1303 (isConstantMemOff() &&
1304 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1305 return true;
1306 MCValue Res;
1307 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1308 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001309 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001310
Simon Atanasyand4d892f2018-04-26 19:55:28 +00001311 bool isMemWithPtrSizeOffset() const {
1312 if (!isMem())
1313 return false;
1314 if (!getMemBase()->isGPRAsmReg())
1315 return false;
1316 const unsigned PtrBits = 32;
1317 if (isa<MCTargetExpr>(getMemOff()) ||
1318 (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
1319 return true;
1320 MCValue Res;
1321 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1322 return IsReloc && isIntN(PtrBits, Res.getConstant());
1323 }
1324
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001325 bool isMemWithGRPMM16Base() const {
1326 return isMem() && getMemBase()->isMM16AsmReg();
1327 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001328
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001329 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1330 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1331 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1332 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001333
Jozef Kolek12c69822014-12-23 16:16:33 +00001334 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1335 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1336 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1337 && (getMemBase()->getGPR32Reg() == Mips::SP);
1338 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001339
Daniel Sanderse473dc92016-05-09 13:38:25 +00001340 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1341 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1342 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1343 && (getMemBase()->getGPR32Reg() == Mips::GP);
1344 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001345
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001346 template <unsigned Bits, unsigned ShiftLeftAmount>
1347 bool isScaledUImm() const {
1348 return isConstantImm() &&
1349 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001350 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001351
Daniel Sanders97297772016-03-22 14:40:00 +00001352 template <unsigned Bits, unsigned ShiftLeftAmount>
1353 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001354 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1355 return true;
1356 // Operand can also be a symbol or symbol plus offset in case of relocations.
1357 if (Kind != k_Immediate)
1358 return false;
1359 MCValue Res;
1360 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1361 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001362 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001363
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001364 bool isRegList16() const {
1365 if (!isRegList())
1366 return false;
1367
1368 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001369 if (Size < 2 || Size > 5)
1370 return false;
1371
1372 unsigned R0 = RegList.List->front();
1373 unsigned R1 = RegList.List->back();
1374 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1375 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001376 return false;
1377
1378 int PrevReg = *RegList.List->begin();
1379 for (int i = 1; i < Size - 1; i++) {
1380 int Reg = (*(RegList.List))[i];
1381 if ( Reg != PrevReg + 1)
1382 return false;
1383 PrevReg = Reg;
1384 }
1385
1386 return true;
1387 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001388
Vladimir Medic2b953d02013-10-01 09:48:56 +00001389 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001390
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001391 bool isLSAImm() const {
1392 if (!isConstantImm())
1393 return false;
1394 int64_t Val = getConstantImm();
1395 return 1 <= Val && Val <= 4;
1396 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001397
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001398 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001399
Zoran Jovanovic41688672015-02-10 16:36:20 +00001400 bool isMovePRegPair() const {
1401 if (Kind != k_RegList || RegList.List->size() != 2)
1402 return false;
1403
1404 unsigned R0 = RegList.List->front();
1405 unsigned R1 = RegList.List->back();
1406
1407 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1408 (R0 == Mips::A1 && R1 == Mips::A3) ||
1409 (R0 == Mips::A2 && R1 == Mips::A3) ||
1410 (R0 == Mips::A0 && R1 == Mips::S5) ||
1411 (R0 == Mips::A0 && R1 == Mips::S6) ||
1412 (R0 == Mips::A0 && R1 == Mips::A1) ||
1413 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001414 (R0 == Mips::A0 && R1 == Mips::A3) ||
1415 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1416 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1417 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1418 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1419 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1420 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1421 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1422 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001423 return true;
1424
1425 return false;
1426 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001427
1428 StringRef getToken() const {
1429 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001430 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001431 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001432
Zlatko Buljanba553a62016-05-09 08:07:28 +00001433 bool isRegPair() const {
1434 return Kind == k_RegPair && RegIdx.Index <= 30;
1435 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001436
Craig Topper56c590a2014-04-29 07:58:02 +00001437 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001438 // As a special case until we sort out the definition of div/divu, accept
1439 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001440 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1441 RegIdx.Kind & RegKind_GPR)
1442 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001443
Daniel Sanders976d9382016-07-05 13:38:40 +00001444 llvm_unreachable("Invalid access!");
1445 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001446 }
1447
Jack Carterb4dbc172012-09-05 23:34:03 +00001448 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001449 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001450 return Imm.Val;
1451 }
1452
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001453 int64_t getConstantImm() const {
1454 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001455 int64_t Value = 0;
1456 (void)Val->evaluateAsAbsolute(Value);
1457 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001458 }
1459
1460 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001461 assert((Kind == k_Memory) && "Invalid access!");
1462 return Mem.Base;
1463 }
1464
1465 const MCExpr *getMemOff() const {
1466 assert((Kind == k_Memory) && "Invalid access!");
1467 return Mem.Off;
1468 }
1469
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001470 int64_t getConstantMemOff() const {
1471 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1472 }
1473
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001474 const SmallVectorImpl<unsigned> &getRegList() const {
1475 assert((Kind == k_RegList) && "Invalid access!");
1476 return *(RegList.List);
1477 }
1478
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001479 unsigned getRegPair() const {
1480 assert((Kind == k_RegPair) && "Invalid access!");
1481 return RegIdx.Index;
1482 }
1483
David Blaikie960ea3f2014-06-08 16:18:35 +00001484 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1485 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001486 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001487 Op->Tok.Data = Str.data();
1488 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001489 Op->StartLoc = S;
1490 Op->EndLoc = S;
1491 return Op;
1492 }
1493
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001494 /// Create a numeric register (e.g. $1). The exact register remains
1495 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001496 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001497 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1498 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001499 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001500 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001501 }
1502
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001503 /// Create a register that is definitely a GPR.
1504 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001505 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001506 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1507 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1508 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001509 }
1510
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001511 /// Create a register that is definitely a FGR.
1512 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001513 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001514 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1515 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1516 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001517 }
1518
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001519 /// Create a register that is definitely a HWReg.
1520 /// This is typically only used for named registers such as $hwr_cpunum.
1521 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001522 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001523 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001524 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001525 }
1526
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001527 /// Create a register that is definitely an FCC.
1528 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001529 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001530 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1531 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1532 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001533 }
1534
1535 /// Create a register that is definitely an ACC.
1536 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001537 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001538 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1539 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1540 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001541 }
1542
1543 /// Create a register that is definitely an MSA128.
1544 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001545 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001546 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1547 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1548 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001549 }
1550
1551 /// Create a register that is definitely an MSACtrl.
1552 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001553 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001554 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1555 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1556 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001557 }
1558
David Blaikie960ea3f2014-06-08 16:18:35 +00001559 static std::unique_ptr<MipsOperand>
1560 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001561 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001562 Op->Imm.Val = Val;
1563 Op->StartLoc = S;
1564 Op->EndLoc = E;
1565 return Op;
1566 }
1567
David Blaikie960ea3f2014-06-08 16:18:35 +00001568 static std::unique_ptr<MipsOperand>
1569 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1570 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001571 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001572 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001573 Op->Mem.Off = Off;
1574 Op->StartLoc = S;
1575 Op->EndLoc = E;
1576 return Op;
1577 }
1578
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001579 static std::unique_ptr<MipsOperand>
1580 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1581 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001582 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001583
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001584 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001585 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001586 Op->StartLoc = StartLoc;
1587 Op->EndLoc = EndLoc;
1588 return Op;
1589 }
1590
Daniel Sandersd044e492016-05-09 13:10:57 +00001591 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1592 SMLoc S, SMLoc E,
1593 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001594 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001595 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001596 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1597 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001598 Op->StartLoc = S;
1599 Op->EndLoc = E;
1600 return Op;
1601 }
1602
Simon Dardis509da1a2017-02-13 16:06:48 +00001603 bool isGPRZeroAsmReg() const {
1604 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1605 }
1606
1607 bool isGPRNonZeroAsmReg() const {
1608 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1609 RegIdx.Index <= 31;
1610 }
1611
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001612 bool isGPRAsmReg() const {
1613 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001614 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001615
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001616 bool isMM16AsmReg() const {
1617 if (!(isRegIdx() && RegIdx.Kind))
1618 return false;
1619 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1620 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001621
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001622 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001623 bool isMM16AsmRegZero() const {
1624 if (!(isRegIdx() && RegIdx.Kind))
1625 return false;
1626 return (RegIdx.Index == 0 ||
1627 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1628 RegIdx.Index == 17);
1629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Zoran Jovanovic41688672015-02-10 16:36:20 +00001631 bool isMM16AsmRegMoveP() const {
1632 if (!(isRegIdx() && RegIdx.Kind))
1633 return false;
1634 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1635 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1636 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001637
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001638 bool isFGRAsmReg() const {
1639 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1640 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001643 bool isStrictlyFGRAsmReg() const {
1644 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1645 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1646 }
1647
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001648 bool isHWRegsAsmReg() const {
1649 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001650 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001651
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001652 bool isCCRAsmReg() const {
1653 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001654 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001655
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001656 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001657 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1658 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001659 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001660 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001661
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001662 bool isACCAsmReg() const {
1663 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001664 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001665
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001666 bool isCOP0AsmReg() const {
1667 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1668 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001669
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001670 bool isCOP2AsmReg() const {
1671 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001672 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001673
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001674 bool isCOP3AsmReg() const {
1675 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1676 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001677
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001678 bool isMSA128AsmReg() const {
1679 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001680 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001681
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001682 bool isMSACtrlAsmReg() const {
1683 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001684 }
1685
Jack Carterb4dbc172012-09-05 23:34:03 +00001686 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001687 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001688 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001689 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001690
Craig Topper56c590a2014-04-29 07:58:02 +00001691 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001692 switch (Kind) {
1693 case k_Immediate:
1694 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001695 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001696 OS << ">";
1697 break;
1698 case k_Memory:
1699 OS << "Mem<";
1700 Mem.Base->print(OS);
1701 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001702 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001703 OS << ">";
1704 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001705 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001706 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1707 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001708 break;
1709 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001710 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001711 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001712 case k_RegList:
1713 OS << "RegList< ";
1714 for (auto Reg : (*RegList.List))
1715 OS << Reg << " ";
1716 OS << ">";
1717 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001718 case k_RegPair:
1719 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1720 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001721 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001722 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001723
1724 bool isValidForTie(const MipsOperand &Other) const {
1725 if (Kind != Other.Kind)
1726 return false;
1727
1728 switch (Kind) {
1729 default:
1730 llvm_unreachable("Unexpected kind");
1731 return false;
1732 case k_RegisterIndex: {
1733 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1734 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1735 return Token == OtherToken;
1736 }
1737 }
1738 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001739}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001740
1741} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001742
Jack Carter9e65aa32013-03-22 00:05:30 +00001743namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001744
Jack Carter9e65aa32013-03-22 00:05:30 +00001745extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001746
1747} // end namespace llvm
1748
Jack Carter9e65aa32013-03-22 00:05:30 +00001749static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1750 return MipsInsts[Opcode];
1751}
1752
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001753static bool hasShortDelaySlot(unsigned Opcode) {
1754 switch (Opcode) {
1755 case Mips::JALS_MM:
1756 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001757 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001758 case Mips::BGEZALS_MM:
1759 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001760 return true;
1761 default:
1762 return false;
1763 }
1764}
1765
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001766static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1767 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1768 return &SRExpr->getSymbol();
1769 }
1770
1771 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1772 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1773 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1774
1775 if (LHSSym)
1776 return LHSSym;
1777
1778 if (RHSSym)
1779 return RHSSym;
1780
1781 return nullptr;
1782 }
1783
1784 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1785 return getSingleMCSymbol(UExpr->getSubExpr());
1786
1787 return nullptr;
1788}
1789
1790static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1791 if (isa<MCSymbolRefExpr>(Expr))
1792 return 1;
1793
1794 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1795 return countMCSymbolRefExpr(BExpr->getLHS()) +
1796 countMCSymbolRefExpr(BExpr->getRHS());
1797
1798 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1799 return countMCSymbolRefExpr(UExpr->getSubExpr());
1800
1801 return 0;
1802}
1803
Jack Carter9e65aa32013-03-22 00:05:30 +00001804bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001805 MCStreamer &Out,
1806 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001807 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001808 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001809 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001810
Jack Carter9e65aa32013-03-22 00:05:30 +00001811 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001812
1813 if (MCID.isBranch() || MCID.isCall()) {
1814 const unsigned Opcode = Inst.getOpcode();
1815 MCOperand Offset;
1816
1817 switch (Opcode) {
1818 default:
1819 break;
Kai Nackee0245392015-01-27 19:11:28 +00001820 case Mips::BBIT0:
1821 case Mips::BBIT032:
1822 case Mips::BBIT1:
1823 case Mips::BBIT132:
1824 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001825 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001826
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001827 case Mips::BEQ:
1828 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001829 case Mips::BEQ_MM:
1830 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001831 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001832 Offset = Inst.getOperand(2);
1833 if (!Offset.isImm())
1834 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001835 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001836 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001837 if (OffsetToAlignment(Offset.getImm(),
1838 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001839 return Error(IDLoc, "branch to misaligned address");
1840 break;
1841 case Mips::BGEZ:
1842 case Mips::BGTZ:
1843 case Mips::BLEZ:
1844 case Mips::BLTZ:
1845 case Mips::BGEZAL:
1846 case Mips::BLTZAL:
1847 case Mips::BC1F:
1848 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001849 case Mips::BGEZ_MM:
1850 case Mips::BGTZ_MM:
1851 case Mips::BLEZ_MM:
1852 case Mips::BLTZ_MM:
1853 case Mips::BGEZAL_MM:
1854 case Mips::BLTZAL_MM:
1855 case Mips::BC1F_MM:
1856 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001857 case Mips::BC1EQZC_MMR6:
1858 case Mips::BC1NEZC_MMR6:
1859 case Mips::BC2EQZC_MMR6:
1860 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001861 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001862 Offset = Inst.getOperand(1);
1863 if (!Offset.isImm())
1864 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001865 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001866 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001867 if (OffsetToAlignment(Offset.getImm(),
1868 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001869 return Error(IDLoc, "branch to misaligned address");
1870 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001871 case Mips::BGEC: case Mips::BGEC_MMR6:
1872 case Mips::BLTC: case Mips::BLTC_MMR6:
1873 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1874 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1875 case Mips::BEQC: case Mips::BEQC_MMR6:
1876 case Mips::BNEC: case Mips::BNEC_MMR6:
1877 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1878 Offset = Inst.getOperand(2);
1879 if (!Offset.isImm())
1880 break; // We'll deal with this situation later on when applying fixups.
1881 if (!isIntN(18, Offset.getImm()))
1882 return Error(IDLoc, "branch target out of range");
1883 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1884 return Error(IDLoc, "branch to misaligned address");
1885 break;
1886 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1887 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1888 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1889 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1890 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1891 Offset = Inst.getOperand(1);
1892 if (!Offset.isImm())
1893 break; // We'll deal with this situation later on when applying fixups.
1894 if (!isIntN(18, Offset.getImm()))
1895 return Error(IDLoc, "branch target out of range");
1896 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1897 return Error(IDLoc, "branch to misaligned address");
1898 break;
1899 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1900 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1901 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1902 Offset = Inst.getOperand(1);
1903 if (!Offset.isImm())
1904 break; // We'll deal with this situation later on when applying fixups.
1905 if (!isIntN(23, Offset.getImm()))
1906 return Error(IDLoc, "branch target out of range");
1907 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1908 return Error(IDLoc, "branch to misaligned address");
1909 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001910 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001911 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001912 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001913 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001914 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1915 Offset = Inst.getOperand(1);
1916 if (!Offset.isImm())
1917 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001918 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001919 return Error(IDLoc, "branch target out of range");
1920 if (OffsetToAlignment(Offset.getImm(), 2LL))
1921 return Error(IDLoc, "branch to misaligned address");
1922 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001923 }
1924 }
1925
Daniel Sandersa84989a2014-06-16 13:25:35 +00001926 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1927 // We still accept it but it is a normal nop.
1928 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1929 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1930 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1931 "nop instruction");
1932 }
1933
Kai Nackee0245392015-01-27 19:11:28 +00001934 if (hasCnMips()) {
1935 const unsigned Opcode = Inst.getOpcode();
1936 MCOperand Opnd;
1937 int Imm;
1938
1939 switch (Opcode) {
1940 default:
1941 break;
1942
1943 case Mips::BBIT0:
1944 case Mips::BBIT032:
1945 case Mips::BBIT1:
1946 case Mips::BBIT132:
1947 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1948 // The offset is handled above
1949 Opnd = Inst.getOperand(1);
1950 if (!Opnd.isImm())
1951 return Error(IDLoc, "expected immediate operand kind");
1952 Imm = Opnd.getImm();
1953 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1954 Opcode == Mips::BBIT1 ? 63 : 31))
1955 return Error(IDLoc, "immediate operand value out of range");
1956 if (Imm > 31) {
1957 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1958 : Mips::BBIT132);
1959 Inst.getOperand(1).setImm(Imm - 32);
1960 }
1961 break;
1962
Kai Nackee0245392015-01-27 19:11:28 +00001963 case Mips::SEQi:
1964 case Mips::SNEi:
1965 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1966 Opnd = Inst.getOperand(2);
1967 if (!Opnd.isImm())
1968 return Error(IDLoc, "expected immediate operand kind");
1969 Imm = Opnd.getImm();
1970 if (!isInt<10>(Imm))
1971 return Error(IDLoc, "immediate operand value out of range");
1972 break;
1973 }
1974 }
1975
Simon Dardis509da1a2017-02-13 16:06:48 +00001976 // Warn on division by zero. We're checking here as all instructions get
1977 // processed here, not just the macros that need expansion.
1978 //
1979 // The MIPS backend models most of the divison instructions and macros as
1980 // three operand instructions. The pre-R6 divide instructions however have
1981 // two operands and explicitly define HI/LO as part of the instruction,
1982 // not in the operands.
1983 unsigned FirstOp = 1;
1984 unsigned SecondOp = 2;
1985 switch (Inst.getOpcode()) {
1986 default:
1987 break;
1988 case Mips::SDivIMacro:
1989 case Mips::UDivIMacro:
1990 case Mips::DSDivIMacro:
1991 case Mips::DUDivIMacro:
1992 if (Inst.getOperand(2).getImm() == 0) {
1993 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1994 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1995 Warning(IDLoc, "dividing zero by zero");
1996 else
1997 Warning(IDLoc, "division by zero");
1998 }
1999 break;
2000 case Mips::DSDIV:
2001 case Mips::SDIV:
2002 case Mips::UDIV:
2003 case Mips::DUDIV:
2004 case Mips::UDIV_MM:
2005 case Mips::SDIV_MM:
2006 FirstOp = 0;
2007 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00002008 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00002009 case Mips::SDivMacro:
2010 case Mips::DSDivMacro:
2011 case Mips::UDivMacro:
2012 case Mips::DUDivMacro:
2013 case Mips::DIV:
2014 case Mips::DIVU:
2015 case Mips::DDIV:
2016 case Mips::DDIVU:
2017 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002018 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002019 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
2020 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
2021 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
2022 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
2023 Warning(IDLoc, "dividing zero by zero");
2024 else
2025 Warning(IDLoc, "division by zero");
2026 }
2027 break;
2028 }
2029
Simon Atanasyan50485142016-12-12 17:40:26 +00002030 // For PIC code convert unconditional jump to unconditional branch.
2031 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2032 inPicMode()) {
2033 MCInst BInst;
2034 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2035 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2036 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2037 BInst.addOperand(Inst.getOperand(0));
2038 Inst = BInst;
2039 }
2040
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002041 // This expansion is not in a function called by tryExpandInstruction()
2042 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002043 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2044 inPicMode()) {
2045 warnIfNoMacro(IDLoc);
2046
2047 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2048
2049 // We can do this expansion if there's only 1 symbol in the argument
2050 // expression.
2051 if (countMCSymbolRefExpr(JalExpr) > 1)
2052 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2053
2054 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002055 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002056 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2057
2058 // FIXME: Add support for label+offset operands (currently causes an error).
2059 // FIXME: Add support for forward-declared local symbols.
2060 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002061 if (JalSym->isInSection() || JalSym->isTemporary() ||
2062 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002063 if (isABI_O32()) {
2064 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002065 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002066 // R_(MICRO)MIPS_GOT16 label
2067 // addiu $25, $25, 0
2068 // R_(MICRO)MIPS_LO16 label
2069 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002070 const MCExpr *Got16RelocExpr =
2071 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2072 const MCExpr *Lo16RelocExpr =
2073 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002074
Daniel Sandersa736b372016-04-29 13:33:12 +00002075 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2076 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2077 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2078 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002079 } else if (isABI_N32() || isABI_N64()) {
2080 // If it's a local symbol and the N32/N64 ABIs are being used,
2081 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002082 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002083 // R_(MICRO)MIPS_GOT_DISP label
2084 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002085 const MCExpr *GotDispRelocExpr =
2086 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002087
Daniel Sandersa736b372016-04-29 13:33:12 +00002088 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2089 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2090 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002091 }
2092 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002093 // If it's an external/weak symbol, we expand to:
2094 // lw/ld $25, 0($gp)
2095 // R_(MICRO)MIPS_CALL16 label
2096 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002097 const MCExpr *Call16RelocExpr =
2098 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002099
Daniel Sandersa736b372016-04-29 13:33:12 +00002100 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2101 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002102 }
2103
2104 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002105 if (IsCpRestoreSet && inMicroMipsMode())
2106 JalrInst.setOpcode(Mips::JALRS_MM);
2107 else
2108 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002109 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2110 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2111
2112 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2113 // This relocation is supposed to be an optimization hint for the linker
2114 // and is not necessary for correctness.
2115
2116 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002117 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002118 }
2119
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002120 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2121 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002122 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 // reference or immediate we may have to expand instructions.
2124 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002125 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002126 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2127 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002128 MCOperand &Op = Inst.getOperand(i);
2129 if (Op.isImm()) {
2130 int MemOffset = Op.getImm();
2131 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002133 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002134 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002135 }
2136 } else if (Op.isExpr()) {
2137 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002138 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002139 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002140 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002141 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002142 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002143 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002144 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002145 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002146 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002147 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002148 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002149 }
2150 }
2151 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002152 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002153 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002154
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002155 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002156 if (MCID.mayLoad()) {
2157 // Try to create 16-bit GP relative load instruction.
2158 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2159 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2160 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2161 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2162 MCOperand &Op = Inst.getOperand(i);
2163 if (Op.isImm()) {
2164 int MemOffset = Op.getImm();
2165 MCOperand &DstReg = Inst.getOperand(0);
2166 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002167 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002168 getContext().getRegisterInfo()->getRegClass(
2169 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002170 (BaseReg.getReg() == Mips::GP ||
2171 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002172
Daniel Sandersa736b372016-04-29 13:33:12 +00002173 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2174 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002175 return false;
2176 }
2177 }
2178 }
2179 } // for
2180 } // if load
2181
2182 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2183
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002184 MCOperand Opnd;
2185 int Imm;
2186
2187 switch (Inst.getOpcode()) {
2188 default:
2189 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002190 case Mips::ADDIUSP_MM:
2191 Opnd = Inst.getOperand(0);
2192 if (!Opnd.isImm())
2193 return Error(IDLoc, "expected immediate operand kind");
2194 Imm = Opnd.getImm();
2195 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2196 Imm % 4 != 0)
2197 return Error(IDLoc, "immediate operand value out of range");
2198 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002199 case Mips::SLL16_MM:
2200 case Mips::SRL16_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 < 1 || Imm > 8)
2206 return Error(IDLoc, "immediate operand value out of range");
2207 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002208 case Mips::LI16_MM:
2209 Opnd = Inst.getOperand(1);
2210 if (!Opnd.isImm())
2211 return Error(IDLoc, "expected immediate operand kind");
2212 Imm = Opnd.getImm();
2213 if (Imm < -1 || Imm > 126)
2214 return Error(IDLoc, "immediate operand value out of range");
2215 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002216 case Mips::ADDIUR2_MM:
2217 Opnd = Inst.getOperand(2);
2218 if (!Opnd.isImm())
2219 return Error(IDLoc, "expected immediate operand kind");
2220 Imm = Opnd.getImm();
2221 if (!(Imm == 1 || Imm == -1 ||
2222 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2223 return Error(IDLoc, "immediate operand value out of range");
2224 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002225 case Mips::ANDI16_MM:
2226 Opnd = Inst.getOperand(2);
2227 if (!Opnd.isImm())
2228 return Error(IDLoc, "expected immediate operand kind");
2229 Imm = Opnd.getImm();
2230 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2231 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2232 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2233 return Error(IDLoc, "immediate operand value out of range");
2234 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002235 case Mips::LBU16_MM:
2236 Opnd = Inst.getOperand(2);
2237 if (!Opnd.isImm())
2238 return Error(IDLoc, "expected immediate operand kind");
2239 Imm = Opnd.getImm();
2240 if (Imm < -1 || Imm > 14)
2241 return Error(IDLoc, "immediate operand value out of range");
2242 break;
2243 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002244 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002245 Opnd = Inst.getOperand(2);
2246 if (!Opnd.isImm())
2247 return Error(IDLoc, "expected immediate operand kind");
2248 Imm = Opnd.getImm();
2249 if (Imm < 0 || Imm > 15)
2250 return Error(IDLoc, "immediate operand value out of range");
2251 break;
2252 case Mips::LHU16_MM:
2253 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002254 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002255 Opnd = Inst.getOperand(2);
2256 if (!Opnd.isImm())
2257 return Error(IDLoc, "expected immediate operand kind");
2258 Imm = Opnd.getImm();
2259 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2260 return Error(IDLoc, "immediate operand value out of range");
2261 break;
2262 case Mips::LW16_MM:
2263 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002264 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002265 Opnd = Inst.getOperand(2);
2266 if (!Opnd.isImm())
2267 return Error(IDLoc, "expected immediate operand kind");
2268 Imm = Opnd.getImm();
2269 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2270 return Error(IDLoc, "immediate operand value out of range");
2271 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002272 case Mips::ADDIUPC_MM:
2273 MCOperand Opnd = Inst.getOperand(1);
2274 if (!Opnd.isImm())
2275 return Error(IDLoc, "expected immediate operand kind");
2276 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002277 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002278 return Error(IDLoc, "immediate operand value out of range");
2279 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002280 }
2281 }
2282
Daniel Sandersd8c07762016-04-18 12:35:36 +00002283 bool FillDelaySlot =
2284 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2285 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002286 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002287
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002288 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002289 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002290 switch (ExpandResult) {
2291 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002292 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002293 break;
2294 case MER_Success:
2295 break;
2296 case MER_Fail:
2297 return true;
2298 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002299
Daniel Sanderscda908a2016-05-16 09:10:13 +00002300 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2301 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002302 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002303 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002304 TOut.updateABIInfo(*this);
2305 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002306
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002307 // If this instruction has a delay slot and .set reorder is active,
2308 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002309 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002310 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2311 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002312 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002313
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002314 if ((Inst.getOpcode() == Mips::JalOneReg ||
2315 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2316 isPicAndNotNxxAbi()) {
2317 if (IsCpRestoreSet) {
2318 // We need a NOP between the JALR and the LW:
2319 // If .set reorder has been used, we've already emitted a NOP.
2320 // If .set noreorder has been used, we need to emit a NOP at this point.
2321 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002322 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2323 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002324
2325 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002326 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002327 } else
2328 Warning(IDLoc, "no .cprestore used in PIC mode");
2329 }
2330
Jack Carter9e65aa32013-03-22 00:05:30 +00002331 return false;
2332}
2333
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002334MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002335MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2336 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002337 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002338 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002339 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002340 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002341 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002342 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002343 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002344 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002345 case Mips::LoadAddrImm64:
2346 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2347 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2348 "expected immediate operand kind");
2349
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002350 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2351 Inst.getOperand(1),
2352 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002353 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002354 ? MER_Fail
2355 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002356 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002357 case Mips::LoadAddrReg64:
2358 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2359 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2360 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2361 "expected immediate operand kind");
2362
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002363 return expandLoadAddress(Inst.getOperand(0).getReg(),
2364 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2365 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002366 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002367 ? MER_Fail
2368 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002369 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002370 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002371 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2372 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002373 case Mips::SWM_MM:
2374 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002375 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2376 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002377 case Mips::JalOneReg:
2378 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002379 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002380 case Mips::BneImm:
2381 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002382 case Mips::BEQLImmMacro:
2383 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002384 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002385 case Mips::BLT:
2386 case Mips::BLE:
2387 case Mips::BGE:
2388 case Mips::BGT:
2389 case Mips::BLTU:
2390 case Mips::BLEU:
2391 case Mips::BGEU:
2392 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002393 case Mips::BLTL:
2394 case Mips::BLEL:
2395 case Mips::BGEL:
2396 case Mips::BGTL:
2397 case Mips::BLTUL:
2398 case Mips::BLEUL:
2399 case Mips::BGEUL:
2400 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002401 case Mips::BLTImmMacro:
2402 case Mips::BLEImmMacro:
2403 case Mips::BGEImmMacro:
2404 case Mips::BGTImmMacro:
2405 case Mips::BLTUImmMacro:
2406 case Mips::BLEUImmMacro:
2407 case Mips::BGEUImmMacro:
2408 case Mips::BGTUImmMacro:
2409 case Mips::BLTLImmMacro:
2410 case Mips::BLELImmMacro:
2411 case Mips::BGELImmMacro:
2412 case Mips::BGTLImmMacro:
2413 case Mips::BLTULImmMacro:
2414 case Mips::BLEULImmMacro:
2415 case Mips::BGEULImmMacro:
2416 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002417 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002418 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002419 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002420 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2421 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002422 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002423 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002424 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2425 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002426 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002427 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002428 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2429 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002430 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002431 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002432 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2433 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002434 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002435 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2436 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002437 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002438 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002439 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002440 case Mips::PseudoTRUNC_W_D:
2441 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2442 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002443
2444 case Mips::LoadImmSingleGPR:
2445 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2446 ? MER_Fail
2447 : MER_Success;
2448 case Mips::LoadImmSingleFGR:
2449 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2450 ? MER_Fail
2451 : MER_Success;
2452 case Mips::LoadImmDoubleGPR:
2453 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2454 ? MER_Fail
2455 : MER_Success;
2456 case Mips::LoadImmDoubleFGR:
2457 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2458 ? MER_Fail
2459 : MER_Success;
2460 case Mips::LoadImmDoubleFGR_32:
2461 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2462 ? MER_Fail
2463 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002464 case Mips::Ulh:
2465 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2466 case Mips::Ulhu:
2467 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002468 case Mips::Ush:
2469 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002470 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002471 case Mips::Usw:
2472 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002473 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002474 case Mips::NORImm64:
2475 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2476 case Mips::SLTImm64:
2477 if (isInt<16>(Inst.getOperand(2).getImm())) {
2478 Inst.setOpcode(Mips::SLTi64);
2479 return MER_NotAMacro;
2480 }
2481 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2482 case Mips::SLTUImm64:
2483 if (isInt<16>(Inst.getOperand(2).getImm())) {
2484 Inst.setOpcode(Mips::SLTiu64);
2485 return MER_NotAMacro;
2486 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002487 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002488 case Mips::ADDi: case Mips::ADDi_MM:
2489 case Mips::ADDiu: case Mips::ADDiu_MM:
2490 case Mips::SLTi: case Mips::SLTi_MM:
2491 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002492 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2493 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2494 int64_t ImmValue = Inst.getOperand(2).getImm();
2495 if (isInt<16>(ImmValue))
2496 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002497 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2498 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002499 }
2500 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002501 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2502 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2503 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002504 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2505 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2506 int64_t ImmValue = Inst.getOperand(2).getImm();
2507 if (isUInt<16>(ImmValue))
2508 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002509 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2510 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002511 }
2512 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002513 case Mips::ROL:
2514 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002515 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002516 case Mips::ROLImm:
2517 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002518 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002519 case Mips::DROL:
2520 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002521 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002522 case Mips::DROLImm:
2523 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002524 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002525 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002526 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002527 case Mips::MULImmMacro:
2528 case Mips::DMULImmMacro:
2529 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2530 case Mips::MULOMacro:
2531 case Mips::DMULOMacro:
2532 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2533 case Mips::MULOUMacro:
2534 case Mips::DMULOUMacro:
2535 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2536 case Mips::DMULMacro:
2537 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002538 case Mips::LDMacro:
2539 case Mips::SDMacro:
2540 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2541 Inst.getOpcode() == Mips::LDMacro)
2542 ? MER_Fail
2543 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002544 case Mips::SEQMacro:
2545 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2546 case Mips::SEQIMacro:
2547 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002548 case Mips::MFTC0: case Mips::MTTC0:
2549 case Mips::MFTGPR: case Mips::MTTGPR:
2550 case Mips::MFTLO: case Mips::MTTLO:
2551 case Mips::MFTHI: case Mips::MTTHI:
2552 case Mips::MFTACX: case Mips::MTTACX:
2553 case Mips::MFTDSP: case Mips::MTTDSP:
2554 case Mips::MFTC1: case Mips::MTTC1:
2555 case Mips::MFTHC1: case Mips::MTTHC1:
2556 case Mips::CFTC1: case Mips::CTTC1:
2557 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 }
Jack Carter30a59822012-10-04 04:03:53 +00002559}
Jack Carter92995f12012-10-06 00:53:28 +00002560
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002561bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002562 MCStreamer &Out,
2563 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002564 MipsTargetStreamer &TOut = getTargetStreamer();
2565
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002566 // Create a JALR instruction which is going to replace the pseudo-JAL.
2567 MCInst JalrInst;
2568 JalrInst.setLoc(IDLoc);
2569 const MCOperand FirstRegOp = Inst.getOperand(0);
2570 const unsigned Opcode = Inst.getOpcode();
2571
2572 if (Opcode == Mips::JalOneReg) {
2573 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002574 if (IsCpRestoreSet && inMicroMipsMode()) {
2575 JalrInst.setOpcode(Mips::JALRS16_MM);
2576 JalrInst.addOperand(FirstRegOp);
2577 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002578 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002579 JalrInst.addOperand(FirstRegOp);
2580 } else {
2581 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002582 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002583 JalrInst.addOperand(FirstRegOp);
2584 }
2585 } else if (Opcode == Mips::JalTwoReg) {
2586 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002587 if (IsCpRestoreSet && inMicroMipsMode())
2588 JalrInst.setOpcode(Mips::JALRS_MM);
2589 else
2590 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002591 JalrInst.addOperand(FirstRegOp);
2592 const MCOperand SecondRegOp = Inst.getOperand(1);
2593 JalrInst.addOperand(SecondRegOp);
2594 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002595 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002596
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002597 // If .set reorder is active and branch instruction has a delay slot,
2598 // emit a NOP after it.
2599 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002600 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2601 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2602 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002603
2604 return false;
2605}
2606
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002607/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002608template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002609 unsigned BitNum = findFirstSet(x);
2610
2611 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2612}
2613
2614/// Load (or add) an immediate into a register.
2615///
2616/// @param ImmValue The immediate to load.
2617/// @param DstReg The register that will hold the immediate.
2618/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2619/// for a simple initialization.
2620/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2621/// @param IsAddress True if the immediate represents an address. False if it
2622/// is an integer.
2623/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002624bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002625 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002626 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2627 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002628 MipsTargetStreamer &TOut = getTargetStreamer();
2629
Toma Tabacu00e98672015-05-01 12:19:27 +00002630 if (!Is32BitImm && !isGP64bit()) {
2631 Error(IDLoc, "instruction requires a 64-bit architecture");
2632 return true;
2633 }
2634
Daniel Sanders03f9c012015-07-14 12:24:22 +00002635 if (Is32BitImm) {
2636 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2637 // Sign extend up to 64-bit so that the predicates match the hardware
2638 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2639 // true.
2640 ImmValue = SignExtend64<32>(ImmValue);
2641 } else {
2642 Error(IDLoc, "instruction requires a 32-bit immediate");
2643 return true;
2644 }
2645 }
2646
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002647 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2648 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2649
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002650 bool UseSrcReg = false;
2651 if (SrcReg != Mips::NoRegister)
2652 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002653
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002654 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002655 if (UseSrcReg &&
2656 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002657 // At this point we need AT to perform the expansions and we exit if it is
2658 // not available.
2659 unsigned ATReg = getATReg(IDLoc);
2660 if (!ATReg)
2661 return true;
2662 TmpReg = ATReg;
2663 }
2664
Daniel Sanders03f9c012015-07-14 12:24:22 +00002665 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002666 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002667 SrcReg = ZeroReg;
2668
2669 // This doesn't quite follow the usual ABI expectations for N32 but matches
2670 // traditional assembler behaviour. N32 would normally use addiu for both
2671 // integers and addresses.
2672 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002673 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002674 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002675 }
2676
Daniel Sandersa736b372016-04-29 13:33:12 +00002677 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002678 return false;
2679 }
2680
2681 if (isUInt<16>(ImmValue)) {
2682 unsigned TmpReg = DstReg;
2683 if (SrcReg == DstReg) {
2684 TmpReg = getATReg(IDLoc);
2685 if (!TmpReg)
2686 return true;
2687 }
2688
Daniel Sandersa736b372016-04-29 13:33:12 +00002689 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002690 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002691 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002692 return false;
2693 }
2694
2695 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002696 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002697
Toma Tabacu79588102015-04-29 10:19:56 +00002698 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2699 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002700 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002701 // Traditional behaviour seems to special case this particular value. It's
2702 // not clear why other masks are handled differently.
2703 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002704 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2705 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002706 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002707 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002708 return false;
2709 }
2710
2711 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002712 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002713 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2714 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002715 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002716 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002717 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002718 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002719 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002720 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002721
Daniel Sandersa736b372016-04-29 13:33:12 +00002722 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002723 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002724 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002725 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002726 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002727 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002728 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002729
2730 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2731 if (Is32BitImm) {
2732 Error(IDLoc, "instruction requires a 32-bit immediate");
2733 return true;
2734 }
2735
2736 // Traditionally, these immediates are shifted as little as possible and as
2737 // such we align the most significant bit to bit 15 of our temporary.
2738 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2739 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2740 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2741 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002742 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2743 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002744
2745 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002746 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002747
2748 return false;
2749 }
2750
2751 warnIfNoMacro(IDLoc);
2752
2753 // The remaining case is packed with a sequence of dsll and ori with zeros
2754 // being omitted and any neighbouring dsll's being coalesced.
2755 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2756
2757 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2758 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002759 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002760 return false;
2761
2762 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2763 // skip it and defer the shift to the next chunk.
2764 unsigned ShiftCarriedForwards = 16;
2765 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2766 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2767
2768 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002769 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2770 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002771 ShiftCarriedForwards = 0;
2772 }
2773
2774 ShiftCarriedForwards += 16;
2775 }
2776 ShiftCarriedForwards -= 16;
2777
2778 // Finish any remaining shifts left by trailing zeros.
2779 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002780 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002781
2782 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002783 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002784
Matheus Almeida3813d572014-06-19 14:39:14 +00002785 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002786}
Jack Carter92995f12012-10-06 00:53:28 +00002787
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002788bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002789 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002790 const MCOperand &ImmOp = Inst.getOperand(1);
2791 assert(ImmOp.isImm() && "expected immediate operand kind");
2792 const MCOperand &DstRegOp = Inst.getOperand(0);
2793 assert(DstRegOp.isReg() && "expected register operand kind");
2794
2795 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002796 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002797 return true;
2798
2799 return false;
2800}
2801
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002802bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2803 const MCOperand &Offset,
2804 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002805 MCStreamer &Out,
2806 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002807 // la can't produce a usable address when addresses are 64-bit.
2808 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2809 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2810 // We currently can't do this because we depend on the equality
2811 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2812 Error(IDLoc, "la used to load 64-bit address");
2813 // Continue as if we had 'dla' instead.
2814 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002815 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002816 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002817
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002818 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002819 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002820 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002821 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002822 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002823
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002824 if (!Offset.isImm())
2825 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002826 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002827
Scott Egerton24557012016-01-21 15:11:01 +00002828 if (!ABI.ArePtrs64bit()) {
2829 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2830 Is32BitAddress = true;
2831 }
2832
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002833 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002834 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002835}
2836
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002837bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2838 unsigned DstReg, unsigned SrcReg,
2839 bool Is32BitSym, SMLoc IDLoc,
2840 MCStreamer &Out,
2841 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002842 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002843 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002844 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002845 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002846
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002847 if (inPicMode() && ABI.IsO32()) {
2848 MCValue Res;
2849 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2850 Error(IDLoc, "expected relocatable expression");
2851 return true;
2852 }
2853 if (Res.getSymB() != nullptr) {
2854 Error(IDLoc, "expected relocatable expression with only one symbol");
2855 return true;
2856 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002857
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002858 // The case where the result register is $25 is somewhat special. If the
2859 // symbol in the final relocation is external and not modified with a
2860 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2861 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002862 Res.getConstant() == 0 &&
2863 !(Res.getSymA()->getSymbol().isInSection() ||
2864 Res.getSymA()->getSymbol().isTemporary() ||
2865 (Res.getSymA()->getSymbol().isELF() &&
2866 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2867 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002868 const MCExpr *CallExpr =
2869 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2870 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2871 MCOperand::createExpr(CallExpr), IDLoc, STI);
2872 return false;
2873 }
2874
2875 // The remaining cases are:
2876 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2877 // >addiu $tmp, $tmp, %lo(offset)
2878 // >addiu $rd, $tmp, $rs
2879 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2880 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2881 // >addiu $rd, $tmp, $rs
2882 // The addiu's marked with a '>' may be omitted if they are redundant. If
2883 // this happens then the last instruction must use $rd as the result
2884 // register.
2885 const MipsMCExpr *GotExpr =
2886 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2887 const MCExpr *LoExpr = nullptr;
2888 if (Res.getSymA()->getSymbol().isInSection() ||
2889 Res.getSymA()->getSymbol().isTemporary())
2890 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2891 else if (Res.getConstant() != 0) {
2892 // External symbols fully resolve the symbol with just the %got(symbol)
2893 // but we must still account for any offset to the symbol for expressions
2894 // like symbol+8.
2895 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2896 }
2897
2898 unsigned TmpReg = DstReg;
2899 if (UseSrcReg &&
2900 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2901 SrcReg)) {
2902 // If $rs is the same as $rd, we need to use AT.
2903 // If it is not available we exit.
2904 unsigned ATReg = getATReg(IDLoc);
2905 if (!ATReg)
2906 return true;
2907 TmpReg = ATReg;
2908 }
2909
2910 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2911 MCOperand::createExpr(GotExpr), IDLoc, STI);
2912
2913 if (LoExpr)
2914 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2915 IDLoc, STI);
2916
2917 if (UseSrcReg)
2918 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2919
2920 return false;
2921 }
2922
Simon Dardisda96c432017-06-30 15:44:27 +00002923 if (inPicMode() && ABI.ArePtrs64bit()) {
2924 MCValue Res;
2925 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2926 Error(IDLoc, "expected relocatable expression");
2927 return true;
2928 }
2929 if (Res.getSymB() != nullptr) {
2930 Error(IDLoc, "expected relocatable expression with only one symbol");
2931 return true;
2932 }
2933
2934 // The case where the result register is $25 is somewhat special. If the
2935 // symbol in the final relocation is external and not modified with a
2936 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2937 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2938 Res.getConstant() == 0 &&
2939 !(Res.getSymA()->getSymbol().isInSection() ||
2940 Res.getSymA()->getSymbol().isTemporary() ||
2941 (Res.getSymA()->getSymbol().isELF() &&
2942 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2943 ELF::STB_LOCAL))) {
2944 const MCExpr *CallExpr =
2945 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2946 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2947 MCOperand::createExpr(CallExpr), IDLoc, STI);
2948 return false;
2949 }
2950
2951 // The remaining cases are:
2952 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2953 // >daddiu $tmp, $tmp, offset
2954 // >daddu $rd, $tmp, $rs
2955 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2956 // this happens then the last instruction must use $rd as the result
2957 // register.
2958 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2959 Res.getSymA(),
2960 getContext());
2961 const MCExpr *LoExpr = nullptr;
2962 if (Res.getConstant() != 0) {
2963 // Symbols fully resolve with just the %got_disp(symbol) but we
2964 // must still account for any offset to the symbol for
2965 // expressions like symbol+8.
2966 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2967
2968 // FIXME: Offsets greater than 16 bits are not yet implemented.
2969 // FIXME: The correct range is a 32-bit sign-extended number.
2970 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2971 Error(IDLoc, "macro instruction uses large offset, which is not "
2972 "currently supported");
2973 return true;
2974 }
2975 }
2976
2977 unsigned TmpReg = DstReg;
2978 if (UseSrcReg &&
2979 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2980 SrcReg)) {
2981 // If $rs is the same as $rd, we need to use AT.
2982 // If it is not available we exit.
2983 unsigned ATReg = getATReg(IDLoc);
2984 if (!ATReg)
2985 return true;
2986 TmpReg = ATReg;
2987 }
2988
2989 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2990 MCOperand::createExpr(GotExpr), IDLoc, STI);
2991
2992 if (LoExpr)
2993 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2994 IDLoc, STI);
2995
2996 if (UseSrcReg)
2997 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2998
2999 return false;
3000 }
3001
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003002 const MipsMCExpr *HiExpr =
3003 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
3004 const MipsMCExpr *LoExpr =
3005 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00003006
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003007 // This is the 64-bit symbol address expansion.
3008 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00003009 // We need AT for the 64-bit expansion in the cases where the optional
3010 // source register is the destination register and for the superscalar
3011 // scheduled form.
3012 //
3013 // If it is not available we exit if the destination is the same as the
3014 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003015
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003016 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003017 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003018 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003019 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003020
Simon Dardis3aa8a902017-02-06 12:43:46 +00003021 bool RdRegIsRsReg =
3022 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3023
3024 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3025 unsigned ATReg = getATReg(IDLoc);
3026
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003027 // If $rs is the same as $rd:
3028 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3029 // daddiu $at, $at, %higher(sym)
3030 // dsll $at, $at, 16
3031 // daddiu $at, $at, %hi(sym)
3032 // dsll $at, $at, 16
3033 // daddiu $at, $at, %lo(sym)
3034 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003035 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3036 STI);
3037 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3038 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3039 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3040 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3041 IDLoc, STI);
3042 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3043 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3044 IDLoc, STI);
3045 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003046
3047 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003048 } else if (canUseATReg() && !RdRegIsRsReg) {
3049 unsigned ATReg = getATReg(IDLoc);
3050
3051 // If the $rs is different from $rd or if $rs isn't specified and we
3052 // have $at available:
3053 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3054 // lui $at, %hi(sym)
3055 // daddiu $rd, $rd, %higher(sym)
3056 // daddiu $at, $at, %lo(sym)
3057 // dsll32 $rd, $rd, 0
3058 // daddu $rd, $rd, $at
3059 // (daddu $rd, $rd, $rs)
3060 //
3061 // Which is preferred for superscalar issue.
3062 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3063 STI);
3064 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3065 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3066 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3067 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3068 IDLoc, STI);
3069 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3070 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3071 if (UseSrcReg)
3072 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3073
3074 return false;
3075 } else if (!canUseATReg() && !RdRegIsRsReg) {
3076 // Otherwise, synthesize the address in the destination register
3077 // serially:
3078 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3079 // daddiu $rd, $rd, %higher(sym)
3080 // dsll $rd, $rd, 16
3081 // daddiu $rd, $rd, %hi(sym)
3082 // dsll $rd, $rd, 16
3083 // daddiu $rd, $rd, %lo(sym)
3084 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3085 STI);
3086 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3087 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3088 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3089 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3090 MCOperand::createExpr(HiExpr), IDLoc, STI);
3091 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3092 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3093 MCOperand::createExpr(LoExpr), IDLoc, STI);
3094 if (UseSrcReg)
3095 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3096
3097 return false;
3098 } else {
3099 // We have a case where SrcReg == DstReg and we don't have $at
3100 // available. We can't expand this case, so error out appropriately.
3101 assert(SrcReg == DstReg && !canUseATReg() &&
3102 "Could have expanded dla but didn't?");
3103 reportParseError(IDLoc,
3104 "pseudo-instruction requires $at, which is not available");
3105 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003106 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003107 }
3108
3109 // And now, the 32-bit symbol address expansion:
3110 // If $rs is the same as $rd:
3111 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3112 // ori $at, $at, %lo(sym)
3113 // addu $rd, $at, $rd
3114 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3115 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3116 // ori $rd, $rd, %lo(sym)
3117 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003118 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003119 if (UseSrcReg &&
3120 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003121 // If $rs is the same as $rd, we need to use AT.
3122 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003123 unsigned ATReg = getATReg(IDLoc);
3124 if (!ATReg)
3125 return true;
3126 TmpReg = ATReg;
3127 }
3128
Daniel Sandersa736b372016-04-29 13:33:12 +00003129 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3130 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3131 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003132
Toma Tabacufb9d1252015-06-22 12:08:39 +00003133 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003134 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003135 else
Scott Egerton24557012016-01-21 15:11:01 +00003136 assert(
3137 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003138
Toma Tabacu674825c2015-06-16 12:16:24 +00003139 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003140}
3141
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003142// Each double-precision register DO-D15 overlaps with two of the single
3143// precision registers F0-F31. As an example, all of the following hold true:
3144// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3145static unsigned nextReg(unsigned Reg) {
3146 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3147 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3148 switch (Reg) {
3149 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3150 case Mips::ZERO: return Mips::AT;
3151 case Mips::AT: return Mips::V0;
3152 case Mips::V0: return Mips::V1;
3153 case Mips::V1: return Mips::A0;
3154 case Mips::A0: return Mips::A1;
3155 case Mips::A1: return Mips::A2;
3156 case Mips::A2: return Mips::A3;
3157 case Mips::A3: return Mips::T0;
3158 case Mips::T0: return Mips::T1;
3159 case Mips::T1: return Mips::T2;
3160 case Mips::T2: return Mips::T3;
3161 case Mips::T3: return Mips::T4;
3162 case Mips::T4: return Mips::T5;
3163 case Mips::T5: return Mips::T6;
3164 case Mips::T6: return Mips::T7;
3165 case Mips::T7: return Mips::S0;
3166 case Mips::S0: return Mips::S1;
3167 case Mips::S1: return Mips::S2;
3168 case Mips::S2: return Mips::S3;
3169 case Mips::S3: return Mips::S4;
3170 case Mips::S4: return Mips::S5;
3171 case Mips::S5: return Mips::S6;
3172 case Mips::S6: return Mips::S7;
3173 case Mips::S7: return Mips::T8;
3174 case Mips::T8: return Mips::T9;
3175 case Mips::T9: return Mips::K0;
3176 case Mips::K0: return Mips::K1;
3177 case Mips::K1: return Mips::GP;
3178 case Mips::GP: return Mips::SP;
3179 case Mips::SP: return Mips::FP;
3180 case Mips::FP: return Mips::RA;
3181 case Mips::RA: return Mips::ZERO;
3182 case Mips::D0: return Mips::F1;
3183 case Mips::D1: return Mips::F3;
3184 case Mips::D2: return Mips::F5;
3185 case Mips::D3: return Mips::F7;
3186 case Mips::D4: return Mips::F9;
3187 case Mips::D5: return Mips::F11;
3188 case Mips::D6: return Mips::F13;
3189 case Mips::D7: return Mips::F15;
3190 case Mips::D8: return Mips::F17;
3191 case Mips::D9: return Mips::F19;
3192 case Mips::D10: return Mips::F21;
3193 case Mips::D11: return Mips::F23;
3194 case Mips::D12: return Mips::F25;
3195 case Mips::D13: return Mips::F27;
3196 case Mips::D14: return Mips::F29;
3197 case Mips::D15: return Mips::F31;
3198 }
3199}
3200
3201// FIXME: This method is too general. In principle we should compute the number
3202// of instructions required to synthesize the immediate inline compared to
3203// synthesizing the address inline and relying on non .text sections.
3204// For static O32 and N32 this may yield a small benefit, for static N64 this is
3205// likely to yield a much larger benefit as we have to synthesize a 64bit
3206// address to load a 64 bit value.
3207bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3208 MCSymbol *Sym) {
3209 unsigned ATReg = getATReg(IDLoc);
3210 if (!ATReg)
3211 return true;
3212
3213 if(IsPicEnabled) {
3214 const MCExpr *GotSym =
3215 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3216 const MipsMCExpr *GotExpr =
3217 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3218
3219 if(isABI_O32() || isABI_N32()) {
3220 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3221 IDLoc, STI);
3222 } else { //isABI_N64()
3223 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3224 IDLoc, STI);
3225 }
3226 } else { //!IsPicEnabled
3227 const MCExpr *HiSym =
3228 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3229 const MipsMCExpr *HiExpr =
3230 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3231
3232 // FIXME: This is technically correct but gives a different result to gas,
3233 // but gas is incomplete there (it has a fixme noting it doesn't work with
3234 // 64-bit addresses).
3235 // FIXME: With -msym32 option, the address expansion for N64 should probably
3236 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3237 // symbol's value is considered sign extended.
3238 if(isABI_O32() || isABI_N32()) {
3239 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3240 } else { //isABI_N64()
3241 const MCExpr *HighestSym =
3242 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3243 const MipsMCExpr *HighestExpr =
3244 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3245 const MCExpr *HigherSym =
3246 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3247 const MipsMCExpr *HigherExpr =
3248 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3249
3250 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3251 STI);
3252 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3253 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3254 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3255 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3256 IDLoc, STI);
3257 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3258 }
3259 }
3260 return false;
3261}
3262
3263bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3264 bool Is64FPU, SMLoc IDLoc,
3265 MCStreamer &Out,
3266 const MCSubtargetInfo *STI) {
3267 MipsTargetStreamer &TOut = getTargetStreamer();
3268 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3269 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3270 "Invalid instruction operand.");
3271
3272 unsigned FirstReg = Inst.getOperand(0).getReg();
3273 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3274
3275 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3276 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3277 // exponent field), convert it to double (e.g. 1 to 1.0)
3278 if ((HiImmOp64 & 0x7ff00000) == 0) {
3279 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3280 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3281 }
3282
3283 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3284 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3285
3286 if (IsSingle) {
3287 // Conversion of a double in an uint64_t to a float in a uint32_t,
3288 // retaining the bit pattern of a float.
3289 uint32_t ImmOp32;
3290 double doubleImm = BitsToDouble(ImmOp64);
3291 float tmp_float = static_cast<float>(doubleImm);
3292 ImmOp32 = FloatToBits(tmp_float);
3293
3294 if (IsGPR) {
3295 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3296 Out, STI))
3297 return true;
3298 return false;
3299 } else {
3300 unsigned ATReg = getATReg(IDLoc);
3301 if (!ATReg)
3302 return true;
3303 if (LoImmOp64 == 0) {
3304 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3305 Out, STI))
3306 return true;
3307 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3308 return false;
3309 }
3310
3311 MCSection *CS = getStreamer().getCurrentSectionOnly();
3312 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3313 // where appropriate.
3314 MCSection *ReadOnlySection = getContext().getELFSection(
3315 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3316
3317 MCSymbol *Sym = getContext().createTempSymbol();
3318 const MCExpr *LoSym =
3319 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3320 const MipsMCExpr *LoExpr =
3321 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3322
3323 getStreamer().SwitchSection(ReadOnlySection);
3324 getStreamer().EmitLabel(Sym, IDLoc);
3325 getStreamer().EmitIntValue(ImmOp32, 4);
3326 getStreamer().SwitchSection(CS);
3327
3328 if(emitPartialAddress(TOut, IDLoc, Sym))
3329 return true;
3330 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3331 MCOperand::createExpr(LoExpr), IDLoc, STI);
3332 }
3333 return false;
3334 }
3335
3336 // if(!IsSingle)
3337 unsigned ATReg = getATReg(IDLoc);
3338 if (!ATReg)
3339 return true;
3340
3341 if (IsGPR) {
3342 if (LoImmOp64 == 0) {
3343 if(isABI_N32() || isABI_N64()) {
3344 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3345 IDLoc, Out, STI))
3346 return true;
3347 return false;
3348 } else {
3349 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3350 IDLoc, Out, STI))
3351 return true;
3352
3353 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3354 IDLoc, Out, STI))
3355 return true;
3356 return false;
3357 }
3358 }
3359
3360 MCSection *CS = getStreamer().getCurrentSectionOnly();
3361 MCSection *ReadOnlySection = getContext().getELFSection(
3362 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3363
3364 MCSymbol *Sym = getContext().createTempSymbol();
3365 const MCExpr *LoSym =
3366 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3367 const MipsMCExpr *LoExpr =
3368 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3369
3370 getStreamer().SwitchSection(ReadOnlySection);
3371 getStreamer().EmitLabel(Sym, IDLoc);
3372 getStreamer().EmitIntValue(HiImmOp64, 4);
3373 getStreamer().EmitIntValue(LoImmOp64, 4);
3374 getStreamer().SwitchSection(CS);
3375
3376 if(emitPartialAddress(TOut, IDLoc, Sym))
3377 return true;
3378 if(isABI_N64())
3379 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3380 MCOperand::createExpr(LoExpr), IDLoc, STI);
3381 else
3382 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3383 MCOperand::createExpr(LoExpr), IDLoc, STI);
3384
3385 if(isABI_N32() || isABI_N64())
3386 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3387 else {
3388 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3389 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3390 }
3391 return false;
3392 } else { // if(!IsGPR && !IsSingle)
3393 if ((LoImmOp64 == 0) &&
3394 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3395 // FIXME: In the case where the constant is zero, we can load the
3396 // register directly from the zero register.
3397 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3398 Out, STI))
3399 return true;
3400 if (isABI_N32() || isABI_N64())
3401 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3402 else if (hasMips32r2()) {
3403 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3404 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3405 } else {
3406 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3407 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3408 }
3409 return false;
3410 }
3411
3412 MCSection *CS = getStreamer().getCurrentSectionOnly();
3413 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3414 // where appropriate.
3415 MCSection *ReadOnlySection = getContext().getELFSection(
3416 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3417
3418 MCSymbol *Sym = getContext().createTempSymbol();
3419 const MCExpr *LoSym =
3420 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3421 const MipsMCExpr *LoExpr =
3422 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3423
3424 getStreamer().SwitchSection(ReadOnlySection);
3425 getStreamer().EmitLabel(Sym, IDLoc);
3426 getStreamer().EmitIntValue(HiImmOp64, 4);
3427 getStreamer().EmitIntValue(LoImmOp64, 4);
3428 getStreamer().SwitchSection(CS);
3429
3430 if(emitPartialAddress(TOut, IDLoc, Sym))
3431 return true;
3432 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3433 MCOperand::createExpr(LoExpr), IDLoc, STI);
3434 }
3435 return false;
3436}
3437
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003438bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3439 MCStreamer &Out,
3440 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003441 MipsTargetStreamer &TOut = getTargetStreamer();
3442
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003443 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3444 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003445
3446 MCOperand Offset = Inst.getOperand(0);
3447 if (Offset.isExpr()) {
3448 Inst.clear();
3449 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003450 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3451 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3452 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003453 } else {
3454 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003455 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003456 // If offset fits into 11 bits then this instruction becomes microMIPS
3457 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003458 if (inMicroMipsMode())
3459 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003460 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003461 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003462 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003463 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003464 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003465 Inst.clear();
3466 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003467 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3468 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3469 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003470 }
3471 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003472 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003473
Zoran Jovanovicada70912015-09-07 11:56:37 +00003474 // If .set reorder is active and branch instruction has a delay slot,
3475 // emit a NOP after it.
3476 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3477 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003478 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003479
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003480 return false;
3481}
3482
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003483bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3484 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003485 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003486 const MCOperand &DstRegOp = Inst.getOperand(0);
3487 assert(DstRegOp.isReg() && "expected register operand kind");
3488
3489 const MCOperand &ImmOp = Inst.getOperand(1);
3490 assert(ImmOp.isImm() && "expected immediate operand kind");
3491
3492 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003493 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3494 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003495
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003496 bool IsLikely = false;
3497
Toma Tabacue1e460d2015-06-11 10:36:10 +00003498 unsigned OpCode = 0;
3499 switch(Inst.getOpcode()) {
3500 case Mips::BneImm:
3501 OpCode = Mips::BNE;
3502 break;
3503 case Mips::BeqImm:
3504 OpCode = Mips::BEQ;
3505 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003506 case Mips::BEQLImmMacro:
3507 OpCode = Mips::BEQL;
3508 IsLikely = true;
3509 break;
3510 case Mips::BNELImmMacro:
3511 OpCode = Mips::BNEL;
3512 IsLikely = true;
3513 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003514 default:
3515 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3516 break;
3517 }
3518
3519 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003520 if (ImmValue == 0) {
3521 if (IsLikely) {
3522 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3523 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3524 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3525 } else
3526 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3527 STI);
3528 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003529 warnIfNoMacro(IDLoc);
3530
3531 unsigned ATReg = getATReg(IDLoc);
3532 if (!ATReg)
3533 return true;
3534
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003535 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003536 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003537 return true;
3538
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003539 if (IsLikely) {
3540 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3541 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3542 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3543 } else
3544 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003545 }
3546 return false;
3547}
3548
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003549void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003550 const MCSubtargetInfo *STI, bool IsLoad,
3551 bool IsImmOpnd) {
3552 if (IsLoad) {
3553 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3554 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003555 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003556 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3557}
3558
3559void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3560 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3561 MipsTargetStreamer &TOut = getTargetStreamer();
3562
3563 unsigned DstReg = Inst.getOperand(0).getReg();
3564 unsigned BaseReg = Inst.getOperand(1).getReg();
3565
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003566 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003567 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3568 unsigned DstRegClassID =
3569 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3570 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3571 (DstRegClassID == Mips::GPR64RegClassID);
3572
3573 if (IsImmOpnd) {
3574 // Try to use DstReg as the temporary.
3575 if (IsGPR && (BaseReg != DstReg)) {
3576 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3577 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3578 STI);
3579 return;
3580 }
3581
Matheus Almeida7de68e72014-06-18 14:46:05 +00003582 // At this point we need AT to perform the expansions and we exit if it is
3583 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003584 unsigned ATReg = getATReg(IDLoc);
3585 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003586 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003587
3588 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3589 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3590 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003591 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003592
Daniel Sandersfba875f2016-04-29 13:43:45 +00003593 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003594 MCOperand LoOperand = MCOperand::createExpr(
3595 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3596 MCOperand HiOperand = MCOperand::createExpr(
3597 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003598
3599 // Try to use DstReg as the temporary.
3600 if (IsGPR && (BaseReg != DstReg)) {
3601 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3602 LoOperand, DstReg, IDLoc, STI);
3603 return;
3604 }
3605
3606 // At this point we need AT to perform the expansions and we exit if it is
3607 // not available.
3608 unsigned ATReg = getATReg(IDLoc);
3609 if (!ATReg)
3610 return;
3611
3612 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3613 LoOperand, ATReg, IDLoc, STI);
3614}
3615
3616void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3617 const MCSubtargetInfo *STI,
3618 bool IsImmOpnd) {
3619 MipsTargetStreamer &TOut = getTargetStreamer();
3620
3621 unsigned SrcReg = Inst.getOperand(0).getReg();
3622 unsigned BaseReg = Inst.getOperand(1).getReg();
3623
Daniel Sanders241c6792016-05-12 14:01:50 +00003624 if (IsImmOpnd) {
3625 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3626 Inst.getOperand(2).getImm(),
3627 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3628 return;
3629 }
3630
Daniel Sandersfba875f2016-04-29 13:43:45 +00003631 unsigned ATReg = getATReg(IDLoc);
3632 if (!ATReg)
3633 return;
3634
Daniel Sandersfba875f2016-04-29 13:43:45 +00003635 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003636 MCOperand LoOperand = MCOperand::createExpr(
3637 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3638 MCOperand HiOperand = MCOperand::createExpr(
3639 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003640 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3641 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003642}
3643
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003644bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3645 MCStreamer &Out,
3646 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003647 unsigned OpNum = Inst.getNumOperands();
3648 unsigned Opcode = Inst.getOpcode();
3649 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3650
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003651 assert(Inst.getOperand(OpNum - 1).isImm() &&
3652 Inst.getOperand(OpNum - 2).isReg() &&
3653 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003654
3655 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3656 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003657 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3658 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3659 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3660 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003661 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003662 if (inMicroMipsMode() && hasMips32r6())
3663 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3664 else
3665 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3666 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003667
3668 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003669 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003670 return false;
3671}
3672
Toma Tabacu1a108322015-06-17 13:20:24 +00003673bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003674 MCStreamer &Out,
3675 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003676 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003677 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003678 unsigned PseudoOpcode = Inst.getOpcode();
3679 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003680 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003681 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3682
3683 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003684 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003685
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003686 unsigned TrgReg;
3687 if (TrgOp.isReg())
3688 TrgReg = TrgOp.getReg();
3689 else if (TrgOp.isImm()) {
3690 warnIfNoMacro(IDLoc);
3691 EmittedNoMacroWarning = true;
3692
3693 TrgReg = getATReg(IDLoc);
3694 if (!TrgReg)
3695 return true;
3696
3697 switch(PseudoOpcode) {
3698 default:
3699 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3700 case Mips::BLTImmMacro:
3701 PseudoOpcode = Mips::BLT;
3702 break;
3703 case Mips::BLEImmMacro:
3704 PseudoOpcode = Mips::BLE;
3705 break;
3706 case Mips::BGEImmMacro:
3707 PseudoOpcode = Mips::BGE;
3708 break;
3709 case Mips::BGTImmMacro:
3710 PseudoOpcode = Mips::BGT;
3711 break;
3712 case Mips::BLTUImmMacro:
3713 PseudoOpcode = Mips::BLTU;
3714 break;
3715 case Mips::BLEUImmMacro:
3716 PseudoOpcode = Mips::BLEU;
3717 break;
3718 case Mips::BGEUImmMacro:
3719 PseudoOpcode = Mips::BGEU;
3720 break;
3721 case Mips::BGTUImmMacro:
3722 PseudoOpcode = Mips::BGTU;
3723 break;
3724 case Mips::BLTLImmMacro:
3725 PseudoOpcode = Mips::BLTL;
3726 break;
3727 case Mips::BLELImmMacro:
3728 PseudoOpcode = Mips::BLEL;
3729 break;
3730 case Mips::BGELImmMacro:
3731 PseudoOpcode = Mips::BGEL;
3732 break;
3733 case Mips::BGTLImmMacro:
3734 PseudoOpcode = Mips::BGTL;
3735 break;
3736 case Mips::BLTULImmMacro:
3737 PseudoOpcode = Mips::BLTUL;
3738 break;
3739 case Mips::BLEULImmMacro:
3740 PseudoOpcode = Mips::BLEUL;
3741 break;
3742 case Mips::BGEULImmMacro:
3743 PseudoOpcode = Mips::BGEUL;
3744 break;
3745 case Mips::BGTULImmMacro:
3746 PseudoOpcode = Mips::BGTUL;
3747 break;
3748 }
3749
3750 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003751 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003752 return true;
3753 }
3754
Toma Tabacu1a108322015-06-17 13:20:24 +00003755 switch (PseudoOpcode) {
3756 case Mips::BLT:
3757 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003758 case Mips::BLTL:
3759 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003760 AcceptsEquality = false;
3761 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003762 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3763 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003764 ZeroSrcOpcode = Mips::BGTZ;
3765 ZeroTrgOpcode = Mips::BLTZ;
3766 break;
3767 case Mips::BLE:
3768 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003769 case Mips::BLEL:
3770 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003771 AcceptsEquality = true;
3772 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003773 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3774 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003775 ZeroSrcOpcode = Mips::BGEZ;
3776 ZeroTrgOpcode = Mips::BLEZ;
3777 break;
3778 case Mips::BGE:
3779 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003780 case Mips::BGEL:
3781 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003782 AcceptsEquality = true;
3783 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003784 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3785 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003786 ZeroSrcOpcode = Mips::BLEZ;
3787 ZeroTrgOpcode = Mips::BGEZ;
3788 break;
3789 case Mips::BGT:
3790 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003791 case Mips::BGTL:
3792 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003793 AcceptsEquality = false;
3794 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003795 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3796 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003797 ZeroSrcOpcode = Mips::BLTZ;
3798 ZeroTrgOpcode = Mips::BGTZ;
3799 break;
3800 default:
3801 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3802 }
3803
Toma Tabacu1a108322015-06-17 13:20:24 +00003804 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3805 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3806 if (IsSrcRegZero && IsTrgRegZero) {
3807 // FIXME: All of these Opcode-specific if's are needed for compatibility
3808 // with GAS' behaviour. However, they may not generate the most efficient
3809 // code in some circumstances.
3810 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003811 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3812 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003813 return false;
3814 }
3815 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003816 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3817 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003818 Warning(IDLoc, "branch is always taken");
3819 return false;
3820 }
3821 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003822 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3823 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003824 Warning(IDLoc, "branch is always taken");
3825 return false;
3826 }
3827 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003828 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3829 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003830 return false;
3831 }
3832 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003833 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3834 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003835 return false;
3836 }
3837 if (AcceptsEquality) {
3838 // If both registers are $0 and the pseudo-branch accepts equality, it
3839 // will always be taken, so we emit an unconditional branch.
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 both registers are $0 and the pseudo-branch does not accept
3846 // equality, it will never be taken, so we don't have to emit anything.
3847 return false;
3848 }
3849 if (IsSrcRegZero || IsTrgRegZero) {
3850 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3851 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3852 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3853 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3854 // the pseudo-branch will never be taken, so we don't emit anything.
3855 // This only applies to unsigned pseudo-branches.
3856 return false;
3857 }
3858 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3859 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3860 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3861 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3862 // the pseudo-branch will always be taken, so we emit an unconditional
3863 // branch.
3864 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003865 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3866 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003867 Warning(IDLoc, "branch is always taken");
3868 return false;
3869 }
3870 if (IsUnsigned) {
3871 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3872 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3873 // the pseudo-branch will be taken only when the non-zero register is
3874 // different from 0, so we emit a BNEZ.
3875 //
3876 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3877 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3878 // the pseudo-branch will be taken only when the non-zero register is
3879 // equal to 0, so we emit a BEQZ.
3880 //
3881 // Because only BLEU and BGEU branch on equality, we can use the
3882 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003883 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3884 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3885 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003886 return false;
3887 }
3888 // If we have a signed pseudo-branch and one of the registers is $0,
3889 // we can use an appropriate compare-to-zero branch. We select which one
3890 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003891 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3892 IsSrcRegZero ? TrgReg : SrcReg,
3893 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003894 return false;
3895 }
3896
3897 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3898 // expansions. If it is not available, we return.
3899 unsigned ATRegNum = getATReg(IDLoc);
3900 if (!ATRegNum)
3901 return true;
3902
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003903 if (!EmittedNoMacroWarning)
3904 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003905
3906 // SLT fits well with 2 of our 4 pseudo-branches:
3907 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3908 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3909 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3910 // This is accomplished by using a BNEZ with the result of the SLT.
3911 //
3912 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003913 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003914 // Because only BGE and BLE branch on equality, we can use the
3915 // AcceptsEquality variable to decide when to emit the BEQZ.
3916 // Note that the order of the SLT arguments doesn't change between
3917 // opposites.
3918 //
3919 // The same applies to the unsigned variants, except that SLTu is used
3920 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003921 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3922 ReverseOrderSLT ? TrgReg : SrcReg,
3923 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003924
Daniel Sandersa736b372016-04-29 13:33:12 +00003925 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3926 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3927 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3928 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003929 return false;
3930}
3931
Simon Dardis509da1a2017-02-13 16:06:48 +00003932// Expand a integer division macro.
3933//
3934// Notably we don't have to emit a warning when encountering $rt as the $zero
3935// register, or 0 as an immediate. processInstruction() has already done that.
3936//
3937// The destination register can only be $zero when expanding (S)DivIMacro or
3938// D(S)DivMacro.
3939
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003940bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3941 const MCSubtargetInfo *STI, const bool IsMips64,
3942 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003943 MipsTargetStreamer &TOut = getTargetStreamer();
3944
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003945 warnIfNoMacro(IDLoc);
3946
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003947 const MCOperand &RdRegOp = Inst.getOperand(0);
3948 assert(RdRegOp.isReg() && "expected register operand kind");
3949 unsigned RdReg = RdRegOp.getReg();
3950
3951 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003952 assert(RsRegOp.isReg() && "expected register operand kind");
3953 unsigned RsReg = RsRegOp.getReg();
3954
Simon Dardis12850ee2017-01-31 10:49:24 +00003955 unsigned RtReg;
3956 int64_t ImmValue;
3957
3958 const MCOperand &RtOp = Inst.getOperand(2);
3959 assert((RtOp.isReg() || RtOp.isImm()) &&
3960 "expected register or immediate operand kind");
3961 if (RtOp.isReg())
3962 RtReg = RtOp.getReg();
3963 else
3964 ImmValue = RtOp.getImm();
3965
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003966 unsigned DivOp;
3967 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003968 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003969
3970 if (IsMips64) {
3971 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3972 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003973 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003974 } else {
3975 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3976 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003977 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003978 }
3979
3980 bool UseTraps = useTraps();
3981
Simon Dardis12850ee2017-01-31 10:49:24 +00003982 if (RtOp.isImm()) {
3983 unsigned ATReg = getATReg(IDLoc);
3984 if (!ATReg)
3985 return true;
3986
3987 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003988 if (UseTraps)
3989 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3990 else
3991 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3992 return false;
3993 }
3994
3995 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003996 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003997 return false;
3998 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003999 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00004000 return false;
4001 } else {
4002 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
4003 false, Inst.getLoc(), Out, STI))
4004 return true;
4005 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
4006 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
4007 return false;
4008 }
4009 return true;
4010 }
4011
Simon Dardis509da1a2017-02-13 16:06:48 +00004012 // If the macro expansion of (d)div(u) would always trap or break, insert
4013 // the trap/break and exit. This gives a different result to GAS. GAS has
4014 // an inconsistency/missed optimization in that not all cases are handled
4015 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004016 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004017 if (UseTraps) {
4018 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004019 return false;
4020 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004021 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4022 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004023 }
4024
Simon Dardis509da1a2017-02-13 16:06:48 +00004025 // Temporary label for first branch traget
4026 MCContext &Context = TOut.getStreamer().getContext();
4027 MCSymbol *BrTarget;
4028 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004029
4030 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004031 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004032 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004033 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004034 BrTarget = Context.createTempSymbol();
4035 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4036 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004037 }
4038
Daniel Sandersa736b372016-04-29 13:33:12 +00004039 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004040
4041 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004042 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004043
4044 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004045 if (!UseTraps)
4046 TOut.getStreamer().EmitLabel(BrTarget);
4047
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004048 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004049 return false;
4050 }
4051
4052 unsigned ATReg = getATReg(IDLoc);
4053 if (!ATReg)
4054 return true;
4055
Simon Dardis509da1a2017-02-13 16:06:48 +00004056 if (!UseTraps)
4057 TOut.getStreamer().EmitLabel(BrTarget);
4058
Daniel Sandersa736b372016-04-29 13:33:12 +00004059 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004060
4061 // Temporary label for the second branch target.
4062 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4063 MCOperand LabelOpEnd =
4064 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4065
4066 // Branch to the mflo instruction.
4067 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4068
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004069 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004070 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4071 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004072 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004073 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004074 }
4075
4076 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004077 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004078 else {
4079 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004080 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004081 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4082 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004083 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004084
4085 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004086 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004087 return false;
4088}
4089
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004090bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004091 SMLoc IDLoc, MCStreamer &Out,
4092 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004093 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004094
4095 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4096 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4097 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4098
4099 unsigned FirstReg = Inst.getOperand(0).getReg();
4100 unsigned SecondReg = Inst.getOperand(1).getReg();
4101 unsigned ThirdReg = Inst.getOperand(2).getReg();
4102
4103 if (hasMips1() && !hasMips2()) {
4104 unsigned ATReg = getATReg(IDLoc);
4105 if (!ATReg)
4106 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004107 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4108 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4109 TOut.emitNop(IDLoc, STI);
4110 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4111 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4112 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4113 TOut.emitNop(IDLoc, STI);
4114 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4115 : Mips::CVT_W_S,
4116 FirstReg, SecondReg, IDLoc, STI);
4117 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4118 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004119 return false;
4120 }
4121
Daniel Sandersa736b372016-04-29 13:33:12 +00004122 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4123 : Mips::TRUNC_W_S,
4124 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004125
4126 return false;
4127}
4128
Daniel Sanders6394ee52015-10-15 14:52:58 +00004129bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004130 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004131 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004132 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004133 }
4134
Toma Tabacud88d79c2015-06-23 14:39:42 +00004135 const MCOperand &DstRegOp = Inst.getOperand(0);
4136 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004137 const MCOperand &SrcRegOp = Inst.getOperand(1);
4138 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004139 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4140 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4141
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004142 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004143 unsigned DstReg = DstRegOp.getReg();
4144 unsigned SrcReg = SrcRegOp.getReg();
4145 int64_t OffsetValue = OffsetImmOp.getImm();
4146
4147 // NOTE: We always need AT for ULHU, as it is always used as the source
4148 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004149 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004150 unsigned ATReg = getATReg(IDLoc);
4151 if (!ATReg)
4152 return true;
4153
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004154 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4155 if (IsLargeOffset) {
4156 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4157 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004158 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004159 }
4160
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004161 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4162 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4163 if (isLittle())
4164 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004165
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004166 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4167 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004168
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004169 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4170 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004171
Daniel Sandersa736b372016-04-29 13:33:12 +00004172 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004173 FirstOffset, IDLoc, STI);
4174 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004175 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004176 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004177
4178 return false;
4179}
4180
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004181bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004182 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004183 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004184 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004185 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004186
4187 const MCOperand &DstRegOp = Inst.getOperand(0);
4188 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004189 const MCOperand &SrcRegOp = Inst.getOperand(1);
4190 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004191 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4192 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4193
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004194 MipsTargetStreamer &TOut = getTargetStreamer();
4195 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004196 unsigned SrcReg = SrcRegOp.getReg();
4197 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004198
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004199 warnIfNoMacro(IDLoc);
4200 unsigned ATReg = getATReg(IDLoc);
4201 if (!ATReg)
4202 return true;
4203
4204 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4205 if (IsLargeOffset) {
4206 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4207 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004208 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004209 }
4210
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004211 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4212 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4213 if (isLittle())
4214 std::swap(FirstOffset, SecondOffset);
4215
4216 if (IsLargeOffset) {
4217 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4218 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4219 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4220 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4221 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4222 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004223 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004224 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4225 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4226 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004227 }
4228
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004229 return false;
4230}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004231
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004232bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4233 const MCSubtargetInfo *STI) {
4234 if (hasMips32r6() || hasMips64r6()) {
4235 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4236 }
4237
4238 const MCOperand &DstRegOp = Inst.getOperand(0);
4239 assert(DstRegOp.isReg() && "expected register operand kind");
4240 const MCOperand &SrcRegOp = Inst.getOperand(1);
4241 assert(SrcRegOp.isReg() && "expected register operand kind");
4242 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4243 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4244
4245 MipsTargetStreamer &TOut = getTargetStreamer();
4246 unsigned DstReg = DstRegOp.getReg();
4247 unsigned SrcReg = SrcRegOp.getReg();
4248 int64_t OffsetValue = OffsetImmOp.getImm();
4249
4250 // Compute left/right load/store offsets.
4251 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4252 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4253 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4254 if (isLittle())
4255 std::swap(LxlOffset, LxrOffset);
4256
4257 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4258 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4259 unsigned TmpReg = SrcReg;
4260 if (IsLargeOffset || DoMove) {
4261 warnIfNoMacro(IDLoc);
4262 TmpReg = getATReg(IDLoc);
4263 if (!TmpReg)
4264 return true;
4265 }
4266
4267 if (IsLargeOffset) {
4268 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4269 IDLoc, Out, STI))
4270 return true;
4271 }
4272
4273 if (DoMove)
4274 std::swap(DstReg, TmpReg);
4275
4276 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4277 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4278 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4279 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4280
4281 if (DoMove)
4282 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004283
4284 return false;
4285}
4286
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004287bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004288 MCStreamer &Out,
4289 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004290 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004291
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004292 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4293 assert(Inst.getOperand(0).isReg() &&
4294 Inst.getOperand(1).isReg() &&
4295 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004296
4297 unsigned ATReg = Mips::NoRegister;
4298 unsigned FinalDstReg = Mips::NoRegister;
4299 unsigned DstReg = Inst.getOperand(0).getReg();
4300 unsigned SrcReg = Inst.getOperand(1).getReg();
4301 int64_t ImmValue = Inst.getOperand(2).getImm();
4302
Simon Dardisaa208812017-02-24 14:34:32 +00004303 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004304
4305 unsigned FinalOpcode = Inst.getOpcode();
4306
4307 if (DstReg == SrcReg) {
4308 ATReg = getATReg(Inst.getLoc());
4309 if (!ATReg)
4310 return true;
4311 FinalDstReg = DstReg;
4312 DstReg = ATReg;
4313 }
4314
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004315 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004316 switch (FinalOpcode) {
4317 default:
4318 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004319 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004320 FinalOpcode = Mips::ADD;
4321 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004322 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004323 FinalOpcode = Mips::ADDu;
4324 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004325 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004326 FinalOpcode = Mips::AND;
4327 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004328 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004329 FinalOpcode = Mips::NOR;
4330 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004331 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004332 FinalOpcode = Mips::OR;
4333 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004334 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004335 FinalOpcode = Mips::SLT;
4336 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004337 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004338 FinalOpcode = Mips::SLTu;
4339 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004340 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004341 FinalOpcode = Mips::XOR;
4342 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004343 case Mips::ADDi_MM:
4344 FinalOpcode = Mips::ADD_MM;
4345 break;
4346 case Mips::ADDiu_MM:
4347 FinalOpcode = Mips::ADDu_MM;
4348 break;
4349 case Mips::ANDi_MM:
4350 FinalOpcode = Mips::AND_MM;
4351 break;
4352 case Mips::ORi_MM:
4353 FinalOpcode = Mips::OR_MM;
4354 break;
4355 case Mips::SLTi_MM:
4356 FinalOpcode = Mips::SLT_MM;
4357 break;
4358 case Mips::SLTiu_MM:
4359 FinalOpcode = Mips::SLTu_MM;
4360 break;
4361 case Mips::XORi_MM:
4362 FinalOpcode = Mips::XOR_MM;
4363 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004364 case Mips::ANDi64:
4365 FinalOpcode = Mips::AND64;
4366 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004367 case Mips::NORImm64:
4368 FinalOpcode = Mips::NOR64;
4369 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004370 case Mips::ORi64:
4371 FinalOpcode = Mips::OR64;
4372 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004373 case Mips::SLTImm64:
4374 FinalOpcode = Mips::SLT64;
4375 break;
4376 case Mips::SLTUImm64:
4377 FinalOpcode = Mips::SLTu64;
4378 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004379 case Mips::XORi64:
4380 FinalOpcode = Mips::XOR64;
4381 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004382 }
4383
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004384 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004385 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004386 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004387 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004388 return false;
4389 }
4390 return true;
4391}
4392
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004393bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4394 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004395 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004396 unsigned ATReg = Mips::NoRegister;
4397 unsigned DReg = Inst.getOperand(0).getReg();
4398 unsigned SReg = Inst.getOperand(1).getReg();
4399 unsigned TReg = Inst.getOperand(2).getReg();
4400 unsigned TmpReg = DReg;
4401
4402 unsigned FirstShift = Mips::NOP;
4403 unsigned SecondShift = Mips::NOP;
4404
4405 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004406 if (DReg == SReg) {
4407 TmpReg = getATReg(Inst.getLoc());
4408 if (!TmpReg)
4409 return true;
4410 }
4411
4412 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004413 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4414 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004415 return false;
4416 }
4417
4418 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004419 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004420 return false;
4421 }
4422
4423 return true;
4424 }
4425
4426 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004427 switch (Inst.getOpcode()) {
4428 default:
4429 llvm_unreachable("unexpected instruction opcode");
4430 case Mips::ROL:
4431 FirstShift = Mips::SRLV;
4432 SecondShift = Mips::SLLV;
4433 break;
4434 case Mips::ROR:
4435 FirstShift = Mips::SLLV;
4436 SecondShift = Mips::SRLV;
4437 break;
4438 }
4439
4440 ATReg = getATReg(Inst.getLoc());
4441 if (!ATReg)
4442 return true;
4443
Daniel Sandersa736b372016-04-29 13:33:12 +00004444 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4445 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4446 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4447 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004448
4449 return false;
4450 }
4451
4452 return true;
4453}
4454
4455bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004456 MCStreamer &Out,
4457 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004458 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004459 unsigned ATReg = Mips::NoRegister;
4460 unsigned DReg = Inst.getOperand(0).getReg();
4461 unsigned SReg = Inst.getOperand(1).getReg();
4462 int64_t ImmValue = Inst.getOperand(2).getImm();
4463
4464 unsigned FirstShift = Mips::NOP;
4465 unsigned SecondShift = Mips::NOP;
4466
4467 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004468 if (Inst.getOpcode() == Mips::ROLImm) {
4469 uint64_t MaxShift = 32;
4470 uint64_t ShiftValue = ImmValue;
4471 if (ImmValue != 0)
4472 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004473 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004474 return false;
4475 }
4476
4477 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004478 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004479 return false;
4480 }
4481
4482 return true;
4483 }
4484
4485 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004486 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004487 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004488 return false;
4489 }
4490
4491 switch (Inst.getOpcode()) {
4492 default:
4493 llvm_unreachable("unexpected instruction opcode");
4494 case Mips::ROLImm:
4495 FirstShift = Mips::SLL;
4496 SecondShift = Mips::SRL;
4497 break;
4498 case Mips::RORImm:
4499 FirstShift = Mips::SRL;
4500 SecondShift = Mips::SLL;
4501 break;
4502 }
4503
4504 ATReg = getATReg(Inst.getLoc());
4505 if (!ATReg)
4506 return true;
4507
Daniel Sandersa736b372016-04-29 13:33:12 +00004508 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4509 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4510 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004511
4512 return false;
4513 }
4514
4515 return true;
4516}
4517
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004518bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4519 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004520 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004521 unsigned ATReg = Mips::NoRegister;
4522 unsigned DReg = Inst.getOperand(0).getReg();
4523 unsigned SReg = Inst.getOperand(1).getReg();
4524 unsigned TReg = Inst.getOperand(2).getReg();
4525 unsigned TmpReg = DReg;
4526
4527 unsigned FirstShift = Mips::NOP;
4528 unsigned SecondShift = Mips::NOP;
4529
4530 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004531 if (TmpReg == SReg) {
4532 TmpReg = getATReg(Inst.getLoc());
4533 if (!TmpReg)
4534 return true;
4535 }
4536
4537 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004538 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4539 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004540 return false;
4541 }
4542
4543 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004544 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004545 return false;
4546 }
4547
4548 return true;
4549 }
4550
4551 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004552 switch (Inst.getOpcode()) {
4553 default:
4554 llvm_unreachable("unexpected instruction opcode");
4555 case Mips::DROL:
4556 FirstShift = Mips::DSRLV;
4557 SecondShift = Mips::DSLLV;
4558 break;
4559 case Mips::DROR:
4560 FirstShift = Mips::DSLLV;
4561 SecondShift = Mips::DSRLV;
4562 break;
4563 }
4564
4565 ATReg = getATReg(Inst.getLoc());
4566 if (!ATReg)
4567 return true;
4568
Daniel Sandersa736b372016-04-29 13:33:12 +00004569 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4570 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4571 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4572 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004573
4574 return false;
4575 }
4576
4577 return true;
4578}
4579
4580bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004581 MCStreamer &Out,
4582 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004583 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004584 unsigned ATReg = Mips::NoRegister;
4585 unsigned DReg = Inst.getOperand(0).getReg();
4586 unsigned SReg = Inst.getOperand(1).getReg();
4587 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4588
4589 unsigned FirstShift = Mips::NOP;
4590 unsigned SecondShift = Mips::NOP;
4591
4592 MCInst TmpInst;
4593
4594 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004595 unsigned FinalOpcode = Mips::NOP;
4596 if (ImmValue == 0)
4597 FinalOpcode = Mips::DROTR;
4598 else if (ImmValue % 32 == 0)
4599 FinalOpcode = Mips::DROTR32;
4600 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4601 if (Inst.getOpcode() == Mips::DROLImm)
4602 FinalOpcode = Mips::DROTR32;
4603 else
4604 FinalOpcode = Mips::DROTR;
4605 } else if (ImmValue >= 33) {
4606 if (Inst.getOpcode() == Mips::DROLImm)
4607 FinalOpcode = Mips::DROTR;
4608 else
4609 FinalOpcode = Mips::DROTR32;
4610 }
4611
4612 uint64_t ShiftValue = ImmValue % 32;
4613 if (Inst.getOpcode() == Mips::DROLImm)
4614 ShiftValue = (32 - ImmValue % 32) % 32;
4615
Daniel Sandersa736b372016-04-29 13:33:12 +00004616 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004617
4618 return false;
4619 }
4620
4621 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004622 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004623 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004624 return false;
4625 }
4626
4627 switch (Inst.getOpcode()) {
4628 default:
4629 llvm_unreachable("unexpected instruction opcode");
4630 case Mips::DROLImm:
4631 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4632 FirstShift = Mips::DSLL;
4633 SecondShift = Mips::DSRL32;
4634 }
4635 if (ImmValue == 32) {
4636 FirstShift = Mips::DSLL32;
4637 SecondShift = Mips::DSRL32;
4638 }
4639 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4640 FirstShift = Mips::DSLL32;
4641 SecondShift = Mips::DSRL;
4642 }
4643 break;
4644 case Mips::DRORImm:
4645 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4646 FirstShift = Mips::DSRL;
4647 SecondShift = Mips::DSLL32;
4648 }
4649 if (ImmValue == 32) {
4650 FirstShift = Mips::DSRL32;
4651 SecondShift = Mips::DSLL32;
4652 }
4653 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4654 FirstShift = Mips::DSRL32;
4655 SecondShift = Mips::DSLL;
4656 }
4657 break;
4658 }
4659
4660 ATReg = getATReg(Inst.getLoc());
4661 if (!ATReg)
4662 return true;
4663
Daniel Sandersa736b372016-04-29 13:33:12 +00004664 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4665 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4666 Inst.getLoc(), STI);
4667 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004668
4669 return false;
4670 }
4671
4672 return true;
4673}
4674
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004675bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4676 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004677 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004678 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4679 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4680
Daniel Sandersa736b372016-04-29 13:33:12 +00004681 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004682 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004683 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004684 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004685 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4686 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004687
4688 return false;
4689}
4690
Simon Dardis3c82a642017-02-08 16:25:05 +00004691bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4692 const MCSubtargetInfo *STI) {
4693 MipsTargetStreamer &TOut = getTargetStreamer();
4694 unsigned ATReg = Mips::NoRegister;
4695 unsigned DstReg = Inst.getOperand(0).getReg();
4696 unsigned SrcReg = Inst.getOperand(1).getReg();
4697 int32_t ImmValue = Inst.getOperand(2).getImm();
4698
4699 ATReg = getATReg(IDLoc);
4700 if (!ATReg)
4701 return true;
4702
4703 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4704
4705 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4706 SrcReg, ATReg, IDLoc, STI);
4707
4708 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4709
4710 return false;
4711}
4712
4713bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4714 const MCSubtargetInfo *STI) {
4715 MipsTargetStreamer &TOut = getTargetStreamer();
4716 unsigned ATReg = Mips::NoRegister;
4717 unsigned DstReg = Inst.getOperand(0).getReg();
4718 unsigned SrcReg = Inst.getOperand(1).getReg();
4719 unsigned TmpReg = Inst.getOperand(2).getReg();
4720
4721 ATReg = getATReg(Inst.getLoc());
4722 if (!ATReg)
4723 return true;
4724
4725 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4726 SrcReg, TmpReg, IDLoc, STI);
4727
4728 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4729
4730 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4731 DstReg, DstReg, 0x1F, IDLoc, STI);
4732
4733 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4734
4735 if (useTraps()) {
4736 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4737 } else {
4738 MCContext & Context = TOut.getStreamer().getContext();
4739 MCSymbol * BrTarget = Context.createTempSymbol();
4740 MCOperand LabelOp =
4741 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4742
4743 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4744 if (AssemblerOptions.back()->isReorder())
4745 TOut.emitNop(IDLoc, STI);
4746 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4747
4748 TOut.getStreamer().EmitLabel(BrTarget);
4749 }
4750 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4751
4752 return false;
4753}
4754
4755bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4756 const MCSubtargetInfo *STI) {
4757 MipsTargetStreamer &TOut = getTargetStreamer();
4758 unsigned ATReg = Mips::NoRegister;
4759 unsigned DstReg = Inst.getOperand(0).getReg();
4760 unsigned SrcReg = Inst.getOperand(1).getReg();
4761 unsigned TmpReg = Inst.getOperand(2).getReg();
4762
4763 ATReg = getATReg(IDLoc);
4764 if (!ATReg)
4765 return true;
4766
4767 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4768 SrcReg, TmpReg, IDLoc, STI);
4769
4770 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4771 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4772 if (useTraps()) {
4773 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4774 } else {
4775 MCContext & Context = TOut.getStreamer().getContext();
4776 MCSymbol * BrTarget = Context.createTempSymbol();
4777 MCOperand LabelOp =
4778 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4779
4780 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4781 if (AssemblerOptions.back()->isReorder())
4782 TOut.emitNop(IDLoc, STI);
4783 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4784
4785 TOut.getStreamer().EmitLabel(BrTarget);
4786 }
4787
4788 return false;
4789}
4790
4791bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4792 const MCSubtargetInfo *STI) {
4793 MipsTargetStreamer &TOut = getTargetStreamer();
4794 unsigned DstReg = Inst.getOperand(0).getReg();
4795 unsigned SrcReg = Inst.getOperand(1).getReg();
4796 unsigned TmpReg = Inst.getOperand(2).getReg();
4797
4798 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4799 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4800
4801 return false;
4802}
4803
Simon Dardisaff4d142016-10-18 14:28:00 +00004804// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4805// lw $<reg+1>>, offset+4($reg2)'
4806// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4807// sw $<reg+1>>, offset+4($reg2)'
4808// for O32.
4809bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4810 MCStreamer &Out,
4811 const MCSubtargetInfo *STI,
4812 bool IsLoad) {
4813 if (!isABI_O32())
4814 return true;
4815
4816 warnIfNoMacro(IDLoc);
4817
4818 MipsTargetStreamer &TOut = getTargetStreamer();
4819 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4820 unsigned FirstReg = Inst.getOperand(0).getReg();
4821 unsigned SecondReg = nextReg(FirstReg);
4822 unsigned BaseReg = Inst.getOperand(1).getReg();
4823 if (!SecondReg)
4824 return true;
4825
4826 warnIfRegIndexIsAT(FirstReg, IDLoc);
4827
4828 assert(Inst.getOperand(2).isImm() &&
4829 "Offset for load macro is not immediate!");
4830
4831 MCOperand &FirstOffset = Inst.getOperand(2);
4832 signed NextOffset = FirstOffset.getImm() + 4;
4833 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4834
4835 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4836 return true;
4837
4838 // For loads, clobber the base register with the second load instead of the
4839 // first if the BaseReg == FirstReg.
4840 if (FirstReg != BaseReg || !IsLoad) {
4841 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4842 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4843 } else {
4844 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4845 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4846 }
4847
4848 return false;
4849}
4850
Simon Dardis43115a12016-11-21 20:30:41 +00004851bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4852 const MCSubtargetInfo *STI) {
4853
4854 warnIfNoMacro(IDLoc);
4855 MipsTargetStreamer &TOut = getTargetStreamer();
4856
4857 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4858 Inst.getOperand(2).getReg() != Mips::ZERO) {
4859 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4860 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4861 IDLoc, STI);
4862 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4863 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4864 return false;
4865 }
4866
4867 unsigned Reg = 0;
4868 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4869 Reg = Inst.getOperand(2).getReg();
4870 } else {
4871 Reg = Inst.getOperand(1).getReg();
4872 }
4873 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4874 return false;
4875}
4876
4877bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4878 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004879 warnIfNoMacro(IDLoc);
4880 MipsTargetStreamer &TOut = getTargetStreamer();
4881
4882 unsigned Opc;
4883 int64_t Imm = Inst.getOperand(2).getImm();
4884 unsigned Reg = Inst.getOperand(1).getReg();
4885
4886 if (Imm == 0) {
4887 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4888 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4889 return false;
4890 } else {
4891
4892 if (Reg == Mips::ZERO) {
4893 Warning(IDLoc, "comparison is always false");
4894 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4895 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4896 return false;
4897 }
4898
4899 if (Imm > -0x8000 && Imm < 0) {
4900 Imm = -Imm;
4901 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4902 } else {
4903 Opc = Mips::XORi;
4904 }
4905 }
4906 if (!isUInt<16>(Imm)) {
4907 unsigned ATReg = getATReg(IDLoc);
4908 if (!ATReg)
4909 return true;
4910
4911 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4912 Out, STI))
4913 return true;
4914
4915 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4916 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4917 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4918 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4919 return false;
4920 }
4921
4922 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4923 Imm, IDLoc, STI);
4924 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4925 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4926 return false;
4927}
4928
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004929// Map the DSP accumulator and control register to the corresponding gpr
4930// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4931// do not map the DSP registers contigously to gpr registers.
4932static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4933 switch (Inst.getOpcode()) {
4934 case Mips::MFTLO:
4935 case Mips::MTTLO:
4936 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4937 case Mips::AC0:
4938 return Mips::ZERO;
4939 case Mips::AC1:
4940 return Mips::A0;
4941 case Mips::AC2:
4942 return Mips::T0;
4943 case Mips::AC3:
4944 return Mips::T4;
4945 default:
4946 llvm_unreachable("Unknown register for 'mttr' alias!");
4947 }
4948 case Mips::MFTHI:
4949 case Mips::MTTHI:
4950 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4951 case Mips::AC0:
4952 return Mips::AT;
4953 case Mips::AC1:
4954 return Mips::A1;
4955 case Mips::AC2:
4956 return Mips::T1;
4957 case Mips::AC3:
4958 return Mips::T5;
4959 default:
4960 llvm_unreachable("Unknown register for 'mttr' alias!");
4961 }
4962 case Mips::MFTACX:
4963 case Mips::MTTACX:
4964 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4965 case Mips::AC0:
4966 return Mips::V0;
4967 case Mips::AC1:
4968 return Mips::A2;
4969 case Mips::AC2:
4970 return Mips::T2;
4971 case Mips::AC3:
4972 return Mips::T6;
4973 default:
4974 llvm_unreachable("Unknown register for 'mttr' alias!");
4975 }
4976 case Mips::MFTDSP:
4977 case Mips::MTTDSP:
4978 return Mips::S0;
4979 default:
4980 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4981 }
4982}
4983
4984// Map the floating point register operand to the corresponding register
4985// operand.
4986static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4987 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4988 case Mips::F0: return Mips::ZERO;
4989 case Mips::F1: return Mips::AT;
4990 case Mips::F2: return Mips::V0;
4991 case Mips::F3: return Mips::V1;
4992 case Mips::F4: return Mips::A0;
4993 case Mips::F5: return Mips::A1;
4994 case Mips::F6: return Mips::A2;
4995 case Mips::F7: return Mips::A3;
4996 case Mips::F8: return Mips::T0;
4997 case Mips::F9: return Mips::T1;
4998 case Mips::F10: return Mips::T2;
4999 case Mips::F11: return Mips::T3;
5000 case Mips::F12: return Mips::T4;
5001 case Mips::F13: return Mips::T5;
5002 case Mips::F14: return Mips::T6;
5003 case Mips::F15: return Mips::T7;
5004 case Mips::F16: return Mips::S0;
5005 case Mips::F17: return Mips::S1;
5006 case Mips::F18: return Mips::S2;
5007 case Mips::F19: return Mips::S3;
5008 case Mips::F20: return Mips::S4;
5009 case Mips::F21: return Mips::S5;
5010 case Mips::F22: return Mips::S6;
5011 case Mips::F23: return Mips::S7;
5012 case Mips::F24: return Mips::T8;
5013 case Mips::F25: return Mips::T9;
5014 case Mips::F26: return Mips::K0;
5015 case Mips::F27: return Mips::K1;
5016 case Mips::F28: return Mips::GP;
5017 case Mips::F29: return Mips::SP;
5018 case Mips::F30: return Mips::FP;
5019 case Mips::F31: return Mips::RA;
5020 default: llvm_unreachable("Unknown register for mttc1 alias!");
5021 }
5022}
5023
5024// Map the coprocessor operand the corresponding gpr register operand.
5025static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5026 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5027 case Mips::COP00: return Mips::ZERO;
5028 case Mips::COP01: return Mips::AT;
5029 case Mips::COP02: return Mips::V0;
5030 case Mips::COP03: return Mips::V1;
5031 case Mips::COP04: return Mips::A0;
5032 case Mips::COP05: return Mips::A1;
5033 case Mips::COP06: return Mips::A2;
5034 case Mips::COP07: return Mips::A3;
5035 case Mips::COP08: return Mips::T0;
5036 case Mips::COP09: return Mips::T1;
5037 case Mips::COP010: return Mips::T2;
5038 case Mips::COP011: return Mips::T3;
5039 case Mips::COP012: return Mips::T4;
5040 case Mips::COP013: return Mips::T5;
5041 case Mips::COP014: return Mips::T6;
5042 case Mips::COP015: return Mips::T7;
5043 case Mips::COP016: return Mips::S0;
5044 case Mips::COP017: return Mips::S1;
5045 case Mips::COP018: return Mips::S2;
5046 case Mips::COP019: return Mips::S3;
5047 case Mips::COP020: return Mips::S4;
5048 case Mips::COP021: return Mips::S5;
5049 case Mips::COP022: return Mips::S6;
5050 case Mips::COP023: return Mips::S7;
5051 case Mips::COP024: return Mips::T8;
5052 case Mips::COP025: return Mips::T9;
5053 case Mips::COP026: return Mips::K0;
5054 case Mips::COP027: return Mips::K1;
5055 case Mips::COP028: return Mips::GP;
5056 case Mips::COP029: return Mips::SP;
5057 case Mips::COP030: return Mips::FP;
5058 case Mips::COP031: return Mips::RA;
5059 default: llvm_unreachable("Unknown register for mttc0 alias!");
5060 }
5061}
5062
5063/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5064/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5065bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5066 const MCSubtargetInfo *STI) {
5067 MipsTargetStreamer &TOut = getTargetStreamer();
5068 unsigned rd = 0;
5069 unsigned u = 1;
5070 unsigned sel = 0;
5071 unsigned h = 0;
5072 bool IsMFTR = false;
5073 switch (Inst.getOpcode()) {
5074 case Mips::MFTC0:
5075 IsMFTR = true;
5076 LLVM_FALLTHROUGH;
5077 case Mips::MTTC0:
5078 u = 0;
5079 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5080 sel = Inst.getOperand(2).getImm();
5081 break;
5082 case Mips::MFTGPR:
5083 IsMFTR = true;
5084 LLVM_FALLTHROUGH;
5085 case Mips::MTTGPR:
5086 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5087 break;
5088 case Mips::MFTLO:
5089 case Mips::MFTHI:
5090 case Mips::MFTACX:
5091 case Mips::MFTDSP:
5092 IsMFTR = true;
5093 LLVM_FALLTHROUGH;
5094 case Mips::MTTLO:
5095 case Mips::MTTHI:
5096 case Mips::MTTACX:
5097 case Mips::MTTDSP:
5098 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5099 sel = 1;
5100 break;
5101 case Mips::MFTHC1:
5102 h = 1;
5103 LLVM_FALLTHROUGH;
5104 case Mips::MFTC1:
5105 IsMFTR = true;
5106 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5107 sel = 2;
5108 break;
5109 case Mips::MTTHC1:
5110 h = 1;
5111 LLVM_FALLTHROUGH;
5112 case Mips::MTTC1:
5113 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5114 sel = 2;
5115 break;
5116 case Mips::CFTC1:
5117 IsMFTR = true;
5118 LLVM_FALLTHROUGH;
5119 case Mips::CTTC1:
5120 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5121 sel = 3;
5122 break;
5123 }
5124 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5125 unsigned Op1 =
5126 IsMFTR ? rd
5127 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5128 : Inst.getOperand(0).getReg());
5129
5130 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5131 STI);
5132 return false;
5133}
5134
Daniel Sandersc5537422016-07-27 13:49:44 +00005135unsigned
5136MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5137 const OperandVector &Operands) {
5138 switch (Inst.getOpcode()) {
5139 default:
5140 return Match_Success;
5141 case Mips::DATI:
5142 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005143 if (static_cast<MipsOperand &>(*Operands[1])
5144 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5145 return Match_Success;
5146 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005147 }
5148}
Simon Dardis730fdb72017-01-16 13:55:58 +00005149
Matheus Almeida595fcab2014-06-11 15:05:56 +00005150unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005151 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005152 // As described by the MIPSR6 spec, daui must not use the zero operand for
5153 // its source operand.
5154 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005155 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5156 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5157 return Match_RequiresNoZeroRegister;
5158 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005159 // As described by the Mips32r2 spec, the registers Rd and Rs for
5160 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005161 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005162 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005163 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005164 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005165 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005166 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005167 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5168 return Match_RequiresDifferentSrcAndDst;
5169 return Match_Success;
5170 case Mips::LWP_MM:
5171 case Mips::LWP_MMR6:
5172 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5173 return Match_RequiresDifferentSrcAndDst;
5174 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005175 case Mips::SYNC:
5176 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5177 return Match_NonZeroOperandForSync;
5178 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005179 case Mips::MFC0:
5180 case Mips::MTC0:
5181 case Mips::MTC2:
5182 case Mips::MFC2:
5183 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5184 return Match_NonZeroOperandForMTCX;
5185 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005186 // As described the MIPSR6 spec, the compact branches that compare registers
5187 // must:
5188 // a) Not use the zero register.
5189 // b) Not use the same register twice.
5190 // c) rs < rt for bnec, beqc.
5191 // NB: For this case, the encoding will swap the operands as their
5192 // ordering doesn't matter. GAS performs this transformation too.
5193 // Hence, that constraint does not have to be enforced.
5194 //
5195 // The compact branches that branch iff the signed addition of two registers
5196 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5197 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005198 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5199 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5200 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5201 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5202 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5203 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005204 case Mips::BLEZC64:
5205 case Mips::BGEZC64:
5206 case Mips::BGTZC64:
5207 case Mips::BLTZC64:
5208 case Mips::BEQZC64:
5209 case Mips::BNEZC64:
5210 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5211 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005212 return Match_RequiresNoZeroRegister;
5213 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005214 case Mips::BGEC: case Mips::BGEC_MMR6:
5215 case Mips::BLTC: case Mips::BLTC_MMR6:
5216 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5217 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5218 case Mips::BEQC: case Mips::BEQC_MMR6:
5219 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005220 case Mips::BGEC64:
5221 case Mips::BLTC64:
5222 case Mips::BGEUC64:
5223 case Mips::BLTUC64:
5224 case Mips::BEQC64:
5225 case Mips::BNEC64:
5226 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5227 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005228 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005229 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5230 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005231 return Match_RequiresNoZeroRegister;
5232 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5233 return Match_RequiresDifferentOperands;
5234 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005235 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005236 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5237 "Operands must be immediates for dins!");
5238 const signed Pos = Inst.getOperand(2).getImm();
5239 const signed Size = Inst.getOperand(3).getImm();
5240 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5241 return Match_RequiresPosSizeRange0_32;
5242 return Match_Success;
5243 }
5244 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005245 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005246 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5247 "Operands must be immediates for dinsm/dinsu!");
5248 const signed Pos = Inst.getOperand(2).getImm();
5249 const signed Size = Inst.getOperand(3).getImm();
5250 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5251 return Match_RequiresPosSizeRange33_64;
5252 return Match_Success;
5253 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005254 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005255 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5256 "Operands must be immediates for DEXTM!");
5257 const signed Pos = Inst.getOperand(2).getImm();
5258 const signed Size = Inst.getOperand(3).getImm();
5259 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5260 return Match_RequiresPosSizeUImm6;
5261 return Match_Success;
5262 }
5263 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005264 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005265 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5266 "Operands must be immediates for dextm/dextu!");
5267 const signed Pos = Inst.getOperand(2).getImm();
5268 const signed Size = Inst.getOperand(3).getImm();
5269 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5270 return Match_RequiresPosSizeRange33_64;
5271 return Match_Success;
5272 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005273 case Mips::CRC32B: case Mips::CRC32CB:
5274 case Mips::CRC32H: case Mips::CRC32CH:
5275 case Mips::CRC32W: case Mips::CRC32CW:
5276 case Mips::CRC32D: case Mips::CRC32CD:
5277 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5278 return Match_RequiresSameSrcAndDst;
5279 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005280 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005281
5282 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5283 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5284 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5285 return Match_NoFCCRegisterForCurrentISA;
5286
5287 return Match_Success;
5288
Matheus Almeida595fcab2014-06-11 15:05:56 +00005289}
5290
Daniel Sanders52da7af2015-11-06 12:11:03 +00005291static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5292 uint64_t ErrorInfo) {
5293 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5294 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5295 if (ErrorLoc == SMLoc())
5296 return Loc;
5297 return ErrorLoc;
5298 }
5299 return Loc;
5300}
5301
David Blaikie960ea3f2014-06-08 16:18:35 +00005302bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5303 OperandVector &Operands,
5304 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005305 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005306 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005307 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005308 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005309 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005310
5311 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005312 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005313 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005314 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005315 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005316 case Match_MissingFeature:
5317 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5318 return true;
5319 case Match_InvalidOperand: {
5320 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005321 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005322 if (ErrorInfo >= Operands.size())
5323 return Error(IDLoc, "too few operands for instruction");
5324
Daniel Sanders52da7af2015-11-06 12:11:03 +00005325 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005326 if (ErrorLoc == SMLoc())
5327 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005328 }
5329
5330 return Error(ErrorLoc, "invalid operand for instruction");
5331 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005332 case Match_NonZeroOperandForSync:
5333 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005334 case Match_NonZeroOperandForMTCX:
5335 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005336 case Match_MnemonicFail:
5337 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005338 case Match_RequiresDifferentSrcAndDst:
5339 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005340 case Match_RequiresDifferentOperands:
5341 return Error(IDLoc, "registers must be different");
5342 case Match_RequiresNoZeroRegister:
5343 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005344 case Match_RequiresSameSrcAndDst:
5345 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005346 case Match_NoFCCRegisterForCurrentISA:
5347 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5348 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005349 case Match_Immz:
5350 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005351 case Match_UImm1_0:
5352 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5353 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005354 case Match_UImm2_0:
5355 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5356 "expected 2-bit unsigned immediate");
5357 case Match_UImm2_1:
5358 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5359 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005360 case Match_UImm3_0:
5361 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5362 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005363 case Match_UImm4_0:
5364 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5365 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005366 case Match_SImm4_0:
5367 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5368 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005369 case Match_UImm5_0:
5370 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5371 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005372 case Match_SImm5_0:
5373 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5374 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005375 case Match_UImm5_1:
5376 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5377 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005378 case Match_UImm5_32:
5379 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5380 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005381 case Match_UImm5_33:
5382 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5383 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005384 case Match_UImm5_0_Report_UImm6:
5385 // This is used on UImm5 operands that have a corresponding UImm5_32
5386 // operand to avoid confusing the user.
5387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5388 "expected 6-bit unsigned immediate");
5389 case Match_UImm5_Lsl2:
5390 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5391 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005392 case Match_UImmRange2_64:
5393 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5394 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005395 case Match_UImm6_0:
5396 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5397 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005398 case Match_UImm6_Lsl2:
5399 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5400 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005401 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005402 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5403 "expected 6-bit signed immediate");
5404 case Match_UImm7_0:
5405 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5406 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005407 case Match_UImm7_N1:
5408 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5409 "expected immediate in range -1 .. 126");
5410 case Match_SImm7_Lsl2:
5411 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5412 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005413 case Match_UImm8_0:
5414 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5415 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005416 case Match_UImm10_0:
5417 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5418 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005419 case Match_SImm10_0:
5420 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5421 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005422 case Match_SImm11_0:
5423 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5424 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005425 case Match_UImm16:
5426 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005427 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005428 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5429 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005430 case Match_SImm16:
5431 case Match_SImm16_Relaxed:
5432 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5433 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005434 case Match_SImm19_Lsl2:
5435 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5436 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005437 case Match_UImm20_0:
5438 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5439 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005440 case Match_UImm26_0:
5441 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5442 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005443 case Match_SImm32:
5444 case Match_SImm32_Relaxed:
5445 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5446 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005447 case Match_UImm32_Coerced:
5448 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5449 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005450 case Match_MemSImm9:
5451 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5452 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005453 case Match_MemSImm10:
5454 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5455 "expected memory with 10-bit signed offset");
5456 case Match_MemSImm10Lsl1:
5457 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5458 "expected memory with 11-bit signed offset and multiple of 2");
5459 case Match_MemSImm10Lsl2:
5460 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5461 "expected memory with 12-bit signed offset and multiple of 4");
5462 case Match_MemSImm10Lsl3:
5463 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5464 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005465 case Match_MemSImm11:
5466 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5467 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005468 case Match_MemSImm12:
5469 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5470 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005471 case Match_MemSImm16:
5472 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5473 "expected memory with 16-bit signed offset");
Simon Atanasyand4d892f2018-04-26 19:55:28 +00005474 case Match_MemSImmPtr:
5475 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5476 "expected memory with 32-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005477 case Match_RequiresPosSizeRange0_32: {
5478 SMLoc ErrorStart = Operands[3]->getStartLoc();
5479 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5480 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5481 SMRange(ErrorStart, ErrorEnd));
5482 }
Simon Dardis55e44672017-09-14 17:27:53 +00005483 case Match_RequiresPosSizeUImm6: {
5484 SMLoc ErrorStart = Operands[3]->getStartLoc();
5485 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5486 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5487 SMRange(ErrorStart, ErrorEnd));
5488 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005489 case Match_RequiresPosSizeRange33_64: {
5490 SMLoc ErrorStart = Operands[3]->getStartLoc();
5491 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5492 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5493 SMRange(ErrorStart, ErrorEnd));
5494 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005495 }
Craig Topper589ceee2015-01-03 08:16:34 +00005496
5497 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005498}
5499
Toma Tabacud9d344b2015-04-27 14:05:04 +00005500void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5501 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5502 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5503 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005504}
5505
Toma Tabacu81496c12015-05-20 08:54:45 +00005506void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5507 if (!AssemblerOptions.back()->isMacro())
5508 Warning(Loc, "macro instruction expanded into multiple instructions");
5509}
5510
Daniel Sandersef638fe2014-10-03 15:37:37 +00005511void
5512MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5513 SMRange Range, bool ShowColors) {
5514 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005515 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005516 ShowColors);
5517}
5518
Jack Carter1ac53222013-02-20 23:11:17 +00005519int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005520 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005521
Vladimir Medic4c299852013-11-06 11:27:05 +00005522 CC = StringSwitch<unsigned>(Name)
5523 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005524 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005525 .Case("a0", 4)
5526 .Case("a1", 5)
5527 .Case("a2", 6)
5528 .Case("a3", 7)
5529 .Case("v0", 2)
5530 .Case("v1", 3)
5531 .Case("s0", 16)
5532 .Case("s1", 17)
5533 .Case("s2", 18)
5534 .Case("s3", 19)
5535 .Case("s4", 20)
5536 .Case("s5", 21)
5537 .Case("s6", 22)
5538 .Case("s7", 23)
5539 .Case("k0", 26)
5540 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005541 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005542 .Case("sp", 29)
5543 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005544 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005545 .Case("ra", 31)
5546 .Case("t0", 8)
5547 .Case("t1", 9)
5548 .Case("t2", 10)
5549 .Case("t3", 11)
5550 .Case("t4", 12)
5551 .Case("t5", 13)
5552 .Case("t6", 14)
5553 .Case("t7", 15)
5554 .Case("t8", 24)
5555 .Case("t9", 25)
5556 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005557
Toma Tabacufda445c2014-09-15 15:33:01 +00005558 if (!(isABI_N32() || isABI_N64()))
5559 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005560
Daniel Sandersef638fe2014-10-03 15:37:37 +00005561 if (12 <= CC && CC <= 15) {
5562 // Name is one of t4-t7
5563 AsmToken RegTok = getLexer().peekTok();
5564 SMRange RegRange = RegTok.getLocRange();
5565
5566 StringRef FixedName = StringSwitch<StringRef>(Name)
5567 .Case("t4", "t0")
5568 .Case("t5", "t1")
5569 .Case("t6", "t2")
5570 .Case("t7", "t3")
5571 .Default("");
5572 assert(FixedName != "" && "Register name is not one of t4-t7.");
5573
5574 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5575 "Did you mean $" + FixedName + "?", RegRange);
5576 }
5577
Toma Tabacufda445c2014-09-15 15:33:01 +00005578 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5579 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5580 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5581 if (8 <= CC && CC <= 11)
5582 CC += 4;
5583
5584 if (CC == -1)
5585 CC = StringSwitch<unsigned>(Name)
5586 .Case("a4", 8)
5587 .Case("a5", 9)
5588 .Case("a6", 10)
5589 .Case("a7", 11)
5590 .Case("kt0", 26)
5591 .Case("kt1", 27)
5592 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005593
5594 return CC;
5595}
Jack Carterd0bd6422013-04-18 00:41:53 +00005596
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005597int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5598 int CC;
5599
5600 CC = StringSwitch<unsigned>(Name)
5601 .Case("hwr_cpunum", 0)
5602 .Case("hwr_synci_step", 1)
5603 .Case("hwr_cc", 2)
5604 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005605 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005606 .Default(-1);
5607
5608 return CC;
5609}
5610
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005611int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005612 if (Name[0] == 'f') {
5613 StringRef NumString = Name.substr(1);
5614 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005615 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005616 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005617 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005618 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005619 return IntVal;
5620 }
5621 return -1;
5622}
Jack Cartera63b16a2012-09-07 00:23:42 +00005623
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005624int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005625 if (Name.startswith("fcc")) {
5626 StringRef NumString = Name.substr(3);
5627 unsigned IntVal;
5628 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005629 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005630 if (IntVal > 7) // There are only 8 fcc registers.
5631 return -1;
5632 return IntVal;
5633 }
5634 return -1;
5635}
5636
5637int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005638 if (Name.startswith("ac")) {
5639 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005640 unsigned IntVal;
5641 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005642 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005643 if (IntVal > 3) // There are only 3 acc registers.
5644 return -1;
5645 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005646 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005647 return -1;
5648}
Jack Carterd0bd6422013-04-18 00:41:53 +00005649
Jack Carter5dc8ac92013-09-25 23:50:44 +00005650int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5651 unsigned IntVal;
5652
5653 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5654 return -1;
5655
5656 if (IntVal > 31)
5657 return -1;
5658
5659 return IntVal;
5660}
5661
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005662int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5663 int CC;
5664
5665 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005666 .Case("msair", 0)
5667 .Case("msacsr", 1)
5668 .Case("msaaccess", 2)
5669 .Case("msasave", 3)
5670 .Case("msamodify", 4)
5671 .Case("msarequest", 5)
5672 .Case("msamap", 6)
5673 .Case("msaunmap", 7)
5674 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005675
5676 return CC;
5677}
5678
Simon Dardis3aa8a902017-02-06 12:43:46 +00005679bool MipsAsmParser::canUseATReg() {
5680 return AssemblerOptions.back()->getATRegIndex() != 0;
5681}
5682
Toma Tabacu89a712b2015-04-15 10:48:56 +00005683unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005684 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005685 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005686 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005687 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005688 return 0;
5689 }
5690 unsigned AT = getReg(
5691 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005692 return AT;
5693}
Jack Carter0b744b32012-10-04 02:29:46 +00005694
Jack Carterd0bd6422013-04-18 00:41:53 +00005695unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005696 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005697}
5698
Toma Tabacu13964452014-09-04 13:23:44 +00005699bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005700 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005701 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005702
Jack Carter30a59822012-10-04 04:03:53 +00005703 // Check if the current operand has a custom associated parser, if so, try to
5704 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005705 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5706 if (ResTy == MatchOperand_Success)
5707 return false;
5708 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5709 // there was a match, but an error occurred, in which case, just return that
5710 // the operand parsing failed.
5711 if (ResTy == MatchOperand_ParseFail)
5712 return true;
5713
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005714 DEBUG(dbgs() << ".. Generic Parser\n");
5715
Jack Carterb4dbc172012-09-05 23:34:03 +00005716 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005717 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005718 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005719 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005720
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005721 // Almost all registers have been parsed by custom parsers. There is only
5722 // one exception to this. $zero (and it's alias $0) will reach this point
5723 // for div, divu, and similar instructions because it is not an operand
5724 // to the instruction definition but an explicit register. Special case
5725 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005726 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005727 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005728
Jack Carterd0bd6422013-04-18 00:41:53 +00005729 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005730 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005731 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005732 return true;
5733
Jack Carter873c7242013-01-12 01:03:14 +00005734 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005735 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005736 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005737 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005738 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005739
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005740 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005741 return false;
5742 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005743 default: {
5744 DEBUG(dbgs() << ".. generic integer expression\n");
5745
5746 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005747 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005748 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005749 return true;
5750
Jack Carter873c7242013-01-12 01:03:14 +00005751 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5752
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005753 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005754 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005755 }
Jack Carter0b744b32012-10-04 02:29:46 +00005756 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005757 return true;
5758}
5759
Jack Carterb5cf5902013-04-17 00:18:04 +00005760bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005761 switch (Expr->getKind()) {
5762 case MCExpr::Constant:
5763 return true;
5764 case MCExpr::SymbolRef:
5765 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005766 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005767 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005768 if (!isEvaluated(BE->getLHS()))
5769 return false;
5770 return isEvaluated(BE->getRHS());
5771 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005772 case MCExpr::Unary:
5773 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005774 case MCExpr::Target:
5775 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005776 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005777 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005778}
Jack Carterd0bd6422013-04-18 00:41:53 +00005779
Jack Carterb4dbc172012-09-05 23:34:03 +00005780bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5781 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005782 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005783 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005784 if (ResTy == MatchOperand_Success) {
5785 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005786 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005787 StartLoc = Operand.getStartLoc();
5788 EndLoc = Operand.getEndLoc();
5789
5790 // AFAIK, we only support numeric registers and named GPR's in CFI
5791 // directives.
5792 // Don't worry about eating tokens before failing. Using an unrecognised
5793 // register is a parse error.
5794 if (Operand.isGPRAsmReg()) {
5795 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005796 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005797 }
5798
5799 return (RegNo == (unsigned)-1);
5800 }
5801
5802 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005803 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005804}
5805
Jack Carterb5cf5902013-04-17 00:18:04 +00005806bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005807 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005808
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005809 if (isParenExpr)
5810 return getParser().parseParenExprOfDepth(0, Res, S);
5811 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005812}
5813
Alex Bradbury58eba092016-11-01 16:32:05 +00005814OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005815MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005816 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005817 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005818 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005819 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005820 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005821 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005822 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005823 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005824
Jack Carterb5cf5902013-04-17 00:18:04 +00005825 if (getLexer().getKind() == AsmToken::LParen) {
5826 Parser.Lex();
5827 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005828 }
5829
Jack Carterb5cf5902013-04-17 00:18:04 +00005830 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005831 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005832 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005833
Jack Carterd0bd6422013-04-18 00:41:53 +00005834 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005835 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005836 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005837 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005838 SMLoc E =
5839 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005840 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005841 return MatchOperand_Success;
5842 }
5843 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005844 SMLoc E =
5845 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005846
Jack Carterd0bd6422013-04-18 00:41:53 +00005847 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005848 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005849 auto Base = MipsOperand::createGPRReg(
5850 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005851 Operands.push_back(
5852 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005853 return MatchOperand_Success;
5854 }
Simon Dardis858915f2016-10-18 15:17:17 +00005855 MCBinaryExpr::Opcode Opcode;
5856 // GAS and LLVM treat comparison operators different. GAS will generate -1
5857 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5858 // highly unlikely to be found in a memory offset expression, we don't
5859 // handle them.
5860 switch (Tok.getKind()) {
5861 case AsmToken::Plus:
5862 Opcode = MCBinaryExpr::Add;
5863 Parser.Lex();
5864 break;
5865 case AsmToken::Minus:
5866 Opcode = MCBinaryExpr::Sub;
5867 Parser.Lex();
5868 break;
5869 case AsmToken::Star:
5870 Opcode = MCBinaryExpr::Mul;
5871 Parser.Lex();
5872 break;
5873 case AsmToken::Pipe:
5874 Opcode = MCBinaryExpr::Or;
5875 Parser.Lex();
5876 break;
5877 case AsmToken::Amp:
5878 Opcode = MCBinaryExpr::And;
5879 Parser.Lex();
5880 break;
5881 case AsmToken::LessLess:
5882 Opcode = MCBinaryExpr::Shl;
5883 Parser.Lex();
5884 break;
5885 case AsmToken::GreaterGreater:
5886 Opcode = MCBinaryExpr::LShr;
5887 Parser.Lex();
5888 break;
5889 case AsmToken::Caret:
5890 Opcode = MCBinaryExpr::Xor;
5891 Parser.Lex();
5892 break;
5893 case AsmToken::Slash:
5894 Opcode = MCBinaryExpr::Div;
5895 Parser.Lex();
5896 break;
5897 case AsmToken::Percent:
5898 Opcode = MCBinaryExpr::Mod;
5899 Parser.Lex();
5900 break;
5901 default:
5902 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5903 return MatchOperand_ParseFail;
5904 }
5905 const MCExpr * NextExpr;
5906 if (getParser().parseExpression(NextExpr))
5907 return MatchOperand_ParseFail;
5908 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005909 }
5910
Jack Carterd0bd6422013-04-18 00:41:53 +00005911 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005912 }
5913
Toma Tabacu13964452014-09-04 13:23:44 +00005914 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005915 if (Res != MatchOperand_Success)
5916 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005917
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005918 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005919 Error(Parser.getTok().getLoc(), "')' expected");
5920 return MatchOperand_ParseFail;
5921 }
5922
Jack Carter873c7242013-01-12 01:03:14 +00005923 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5924
Jack Carterd0bd6422013-04-18 00:41:53 +00005925 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005926
Craig Topper062a2ba2014-04-25 05:30:21 +00005927 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005928 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005929
Jack Carterd0bd6422013-04-18 00:41:53 +00005930 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005931 std::unique_ptr<MipsOperand> op(
5932 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005933 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005934 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005935 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005936 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005937 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5938 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005939 if (IdVal->evaluateAsAbsolute(Imm))
5940 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005941 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005942 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005943 getContext());
5944 }
5945
David Blaikie960ea3f2014-06-08 16:18:35 +00005946 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005947 return MatchOperand_Success;
5948}
5949
David Blaikie960ea3f2014-06-08 16:18:35 +00005950bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005951 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005952 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005953 if (Sym) {
5954 SMLoc S = Parser.getTok().getLoc();
5955 const MCExpr *Expr;
5956 if (Sym->isVariable())
5957 Expr = Sym->getVariableValue();
5958 else
5959 return false;
5960 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005961 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005962 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005963 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005964 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005965 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005966 if (ResTy == MatchOperand_Success) {
5967 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005968 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005969 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005970 llvm_unreachable("Should never ParseFail");
5971 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005972 }
Jack Carterd76b2372013-03-21 21:44:16 +00005973 }
5974 }
5975 return false;
5976}
Jack Carterd0bd6422013-04-18 00:41:53 +00005977
Alex Bradbury58eba092016-11-01 16:32:05 +00005978OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005979MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005980 StringRef Identifier,
5981 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005982 int Index = matchCPURegisterName(Identifier);
5983 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005984 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005985 Index, Identifier, getContext().getRegisterInfo(), S,
5986 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005987 return MatchOperand_Success;
5988 }
5989
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005990 Index = matchHWRegsRegisterName(Identifier);
5991 if (Index != -1) {
5992 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005993 Index, Identifier, getContext().getRegisterInfo(), S,
5994 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005995 return MatchOperand_Success;
5996 }
5997
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005998 Index = matchFPURegisterName(Identifier);
5999 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006000 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006001 Index, Identifier, getContext().getRegisterInfo(), S,
6002 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006003 return MatchOperand_Success;
6004 }
6005
6006 Index = matchFCCRegisterName(Identifier);
6007 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006008 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006009 Index, Identifier, getContext().getRegisterInfo(), S,
6010 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006011 return MatchOperand_Success;
6012 }
6013
6014 Index = matchACRegisterName(Identifier);
6015 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006016 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006017 Index, Identifier, getContext().getRegisterInfo(), S,
6018 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006019 return MatchOperand_Success;
6020 }
6021
6022 Index = matchMSA128RegisterName(Identifier);
6023 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006024 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006025 Index, Identifier, getContext().getRegisterInfo(), S,
6026 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006027 return MatchOperand_Success;
6028 }
6029
6030 Index = matchMSA128CtrlRegisterName(Identifier);
6031 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006032 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006033 Index, Identifier, getContext().getRegisterInfo(), S,
6034 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006035 return MatchOperand_Success;
6036 }
6037
6038 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006039}
6040
Alex Bradbury58eba092016-11-01 16:32:05 +00006041OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006042MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006043 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00006044 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006045
6046 if (Token.is(AsmToken::Identifier)) {
6047 DEBUG(dbgs() << ".. identifier\n");
6048 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006049 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006050 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006051 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006052 } else if (Token.is(AsmToken::Integer)) {
6053 DEBUG(dbgs() << ".. integer\n");
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006054 int64_t RegNum = Token.getIntVal();
6055 if (RegNum < 0 || RegNum > 31) {
6056 // Show the error, but treat invalid register
6057 // number as a normal one to continue parsing
6058 // and catch other possible errors.
6059 Error(getLexer().getLoc(), "invalid register number");
6060 }
Toma Tabacu13964452014-09-04 13:23:44 +00006061 Operands.push_back(MipsOperand::createNumericReg(
Simon Atanasyan9df3be32018-04-24 16:14:00 +00006062 RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Daniel Sandersc5537422016-07-27 13:49:44 +00006063 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006064 return MatchOperand_Success;
6065 }
6066
6067 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
6068
6069 return MatchOperand_NoMatch;
6070}
6071
Alex Bradbury58eba092016-11-01 16:32:05 +00006072OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006073MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006074 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006075 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006076
6077 auto Token = Parser.getTok();
6078
6079 SMLoc S = Token.getLoc();
6080
6081 if (Token.isNot(AsmToken::Dollar)) {
6082 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
6083 if (Token.is(AsmToken::Identifier)) {
6084 if (searchSymbolAlias(Operands))
6085 return MatchOperand_Success;
6086 }
6087 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
6088 return MatchOperand_NoMatch;
6089 }
6090 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006091
Toma Tabacu13964452014-09-04 13:23:44 +00006092 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006093 if (ResTy == MatchOperand_Success) {
6094 Parser.Lex(); // $
6095 Parser.Lex(); // identifier
6096 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006097 return ResTy;
6098}
6099
Alex Bradbury58eba092016-11-01 16:32:05 +00006100OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006101MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006102 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006103 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006104
6105 SMLoc S = getLexer().getLoc();
6106
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006107 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006108 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006109 if (ResTy != MatchOperand_NoMatch)
6110 return ResTy;
6111
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006112 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006113 const MCExpr *Expr = nullptr;
6114 if (Parser.parseExpression(Expr)) {
6115 // We have no way of knowing if a symbol was consumed so we must ParseFail
6116 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006117 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006118 Operands.push_back(
6119 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006120 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006121}
6122
Alex Bradbury58eba092016-11-01 16:32:05 +00006123OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006124MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006125 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006126 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006127 // If the first token is '$' we may have register operand. We have to reject
6128 // cases where it is not a register. Complicating the matter is that
6129 // register names are not reserved across all ABIs.
6130 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006131 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006132 if (Parser.getTok().is(AsmToken::Dollar)) {
6133 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6134 ? MatchOperand_ParseFail
6135 : MatchOperand_NoMatch;
6136 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006137 if (getParser().parseExpression(IdVal))
6138 return MatchOperand_ParseFail;
6139 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006140 if (!MCE)
6141 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006142 int64_t Val = MCE->getValue();
6143 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6144 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006145 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006146 return MatchOperand_Success;
6147}
6148
Alex Bradbury58eba092016-11-01 16:32:05 +00006149OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006150MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6151 MCAsmParser &Parser = getParser();
6152 SmallVector<unsigned, 10> Regs;
6153 unsigned RegNo;
6154 unsigned PrevReg = Mips::NoRegister;
6155 bool RegRange = false;
6156 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6157
6158 if (Parser.getTok().isNot(AsmToken::Dollar))
6159 return MatchOperand_ParseFail;
6160
6161 SMLoc S = Parser.getTok().getLoc();
6162 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6163 SMLoc E = getLexer().getLoc();
6164 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6165 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6166 if (RegRange) {
6167 // Remove last register operand because registers from register range
6168 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006169 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6170 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006171 Regs.push_back(RegNo);
6172 } else {
6173 unsigned TmpReg = PrevReg + 1;
6174 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006175 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6176 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6177 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006178 Error(E, "invalid register operand");
6179 return MatchOperand_ParseFail;
6180 }
6181
6182 PrevReg = TmpReg;
6183 Regs.push_back(TmpReg++);
6184 }
6185 }
6186
6187 RegRange = false;
6188 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006189 if ((PrevReg == Mips::NoRegister) &&
6190 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6191 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006192 Error(E, "$16 or $31 expected");
6193 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006194 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6195 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6196 !isGP64bit()) ||
6197 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6198 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6199 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006200 Error(E, "invalid register operand");
6201 return MatchOperand_ParseFail;
6202 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006203 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6204 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6205 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006206 Error(E, "consecutive register numbers expected");
6207 return MatchOperand_ParseFail;
6208 }
6209
6210 Regs.push_back(RegNo);
6211 }
6212
6213 if (Parser.getTok().is(AsmToken::Minus))
6214 RegRange = true;
6215
6216 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6217 !Parser.getTok().isNot(AsmToken::Comma)) {
6218 Error(E, "',' or '-' expected");
6219 return MatchOperand_ParseFail;
6220 }
6221
6222 Lex(); // Consume comma or minus
6223 if (Parser.getTok().isNot(AsmToken::Dollar))
6224 break;
6225
6226 PrevReg = RegNo;
6227 }
6228
6229 SMLoc E = Parser.getTok().getLoc();
6230 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6231 parseMemOperand(Operands);
6232 return MatchOperand_Success;
6233}
6234
Alex Bradbury58eba092016-11-01 16:32:05 +00006235OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006236MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6237 MCAsmParser &Parser = getParser();
6238
6239 SMLoc S = Parser.getTok().getLoc();
6240 if (parseAnyRegister(Operands) != MatchOperand_Success)
6241 return MatchOperand_ParseFail;
6242
6243 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006244 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006245
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006246 Operands.pop_back();
6247 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006248 return MatchOperand_Success;
6249}
6250
Alex Bradbury58eba092016-11-01 16:32:05 +00006251OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006252MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6253 MCAsmParser &Parser = getParser();
6254 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6255 SmallVector<unsigned, 10> Regs;
6256
6257 if (Parser.getTok().isNot(AsmToken::Dollar))
6258 return MatchOperand_ParseFail;
6259
6260 SMLoc S = Parser.getTok().getLoc();
6261
6262 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6263 return MatchOperand_ParseFail;
6264
6265 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6266 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6267 Regs.push_back(RegNo);
6268
6269 SMLoc E = Parser.getTok().getLoc();
6270 if (Parser.getTok().isNot(AsmToken::Comma)) {
6271 Error(E, "',' expected");
6272 return MatchOperand_ParseFail;
6273 }
6274
6275 // Remove comma.
6276 Parser.Lex();
6277
6278 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6279 return MatchOperand_ParseFail;
6280
6281 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6282 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6283 Regs.push_back(RegNo);
6284
6285 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6286
6287 return MatchOperand_Success;
6288}
6289
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006290/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6291/// either this.
6292/// ::= '(', register, ')'
6293/// handle it before we iterate so we don't get tripped up by the lack of
6294/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006295bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006296 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006297 if (getLexer().is(AsmToken::LParen)) {
6298 Operands.push_back(
6299 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6300 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006301 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006302 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006303 return Error(Loc, "unexpected token in argument list");
6304 }
6305 if (Parser.getTok().isNot(AsmToken::RParen)) {
6306 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006307 return Error(Loc, "unexpected token, expected ')'");
6308 }
6309 Operands.push_back(
6310 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6311 Parser.Lex();
6312 }
6313 return false;
6314}
6315
6316/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6317/// either one of these.
6318/// ::= '[', register, ']'
6319/// ::= '[', integer, ']'
6320/// handle it before we iterate so we don't get tripped up by the lack of
6321/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006322bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006323 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006324 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006325 if (getLexer().is(AsmToken::LBrac)) {
6326 Operands.push_back(
6327 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6328 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006329 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006330 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006331 return Error(Loc, "unexpected token in argument list");
6332 }
6333 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6334 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006335 return Error(Loc, "unexpected token, expected ']'");
6336 }
6337 Operands.push_back(
6338 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6339 Parser.Lex();
6340 }
6341 return false;
6342}
6343
David Blaikie960ea3f2014-06-08 16:18:35 +00006344bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6345 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006346 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006347 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006348
6349 // We have reached first instruction, module directive are now forbidden.
6350 getTargetStreamer().forbidModuleDirective();
6351
Vladimir Medic74593e62013-07-17 15:00:42 +00006352 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006353 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006354 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006355 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006356 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006357 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006358
6359 // Read the remaining operands.
6360 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6361 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006362 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006363 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006364 return Error(Loc, "unexpected token in argument list");
6365 }
Toma Tabacu13964452014-09-04 13:23:44 +00006366 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006367 return true;
6368 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006369
Jack Carterd0bd6422013-04-18 00:41:53 +00006370 while (getLexer().is(AsmToken::Comma)) {
6371 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006372 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006373 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006374 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006375 return Error(Loc, "unexpected token in argument list");
6376 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006377 // Parse bracket and parenthesis suffixes before we iterate
6378 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006379 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006380 return true;
6381 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006382 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006383 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006384 }
6385 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6387 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006388 return Error(Loc, "unexpected token in argument list");
6389 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006390 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006391 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006392}
6393
Nirav Dave996fc132016-05-05 14:15:46 +00006394// FIXME: Given that these have the same name, these should both be
6395// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006396bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006397 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006398 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006399}
6400
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006401bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006402 return Error(Loc, ErrorMsg);
6403}
6404
Jack Carter0b744b32012-10-04 02:29:46 +00006405bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006406 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006407 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006408
6409 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006410 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006411
6412 Parser.Lex(); // Eat "noat".
6413
Jack Carterd0bd6422013-04-18 00:41:53 +00006414 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006416 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006417 return false;
6418 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006419
6420 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006421 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006422 return false;
6423}
Jack Carterd0bd6422013-04-18 00:41:53 +00006424
Jack Carter0b744b32012-10-04 02:29:46 +00006425bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006426 // Line can be: ".set at", which sets $at to $1
6427 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006428 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006429 Parser.Lex(); // Eat "at".
6430
Jack Carter0b744b32012-10-04 02:29:46 +00006431 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006432 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006433 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006434
6435 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006436 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006437 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006438 }
6439
6440 if (getLexer().isNot(AsmToken::Equal)) {
6441 reportParseError("unexpected token, expected equals sign");
6442 return false;
6443 }
6444 Parser.Lex(); // Eat "=".
6445
6446 if (getLexer().isNot(AsmToken::Dollar)) {
6447 if (getLexer().is(AsmToken::EndOfStatement)) {
6448 reportParseError("no register specified");
6449 return false;
6450 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006451 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006452 return false;
6453 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006454 }
6455 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006456
Toma Tabacu16a74492015-02-13 10:30:57 +00006457 // Find out what "reg" is.
6458 unsigned AtRegNo;
6459 const AsmToken &Reg = Parser.getTok();
6460 if (Reg.is(AsmToken::Identifier)) {
6461 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6462 } else if (Reg.is(AsmToken::Integer)) {
6463 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006464 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006465 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006466 return false;
6467 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006468
6469 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006470 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006471 reportParseError("invalid register");
6472 return false;
6473 }
6474 Parser.Lex(); // Eat "reg".
6475
6476 // If this is not the end of the statement, report an error.
6477 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6478 reportParseError("unexpected token, expected end of statement");
6479 return false;
6480 }
6481
6482 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6483
6484 Parser.Lex(); // Consume the EndOfStatement.
6485 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006486}
6487
6488bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006489 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006490 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006491 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006492 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006493 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006494 return false;
6495 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006496 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006497 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006498 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006499 return false;
6500}
6501
6502bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006503 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006504 Parser.Lex();
6505 // If this is not the end of the statement, report an error.
6506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006507 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006508 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006509 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006510 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006511 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006512 Parser.Lex(); // Consume the EndOfStatement.
6513 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006514}
6515
6516bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006517 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006518 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006519 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006520 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006521 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006522 return false;
6523 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006524 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006525 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006526 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006527 return false;
6528}
6529
6530bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006531 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006532 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006533 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006534 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006535 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006536 return false;
6537 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006538 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006539 reportParseError("`noreorder' must be set before `nomacro'");
6540 return false;
6541 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006542 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006543 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006544 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006545 return false;
6546}
Jack Carterd76b2372013-03-21 21:44:16 +00006547
Daniel Sanders44934432014-08-07 12:03:36 +00006548bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006549 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006550 Parser.Lex();
6551
6552 // If this is not the end of the statement, report an error.
6553 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006554 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006555
6556 setFeatureBits(Mips::FeatureMSA, "msa");
6557 getTargetStreamer().emitDirectiveSetMsa();
6558 return false;
6559}
6560
6561bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006562 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006563 Parser.Lex();
6564
6565 // If this is not the end of the statement, report an error.
6566 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006567 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006568
6569 clearFeatureBits(Mips::FeatureMSA, "msa");
6570 getTargetStreamer().emitDirectiveSetNoMsa();
6571 return false;
6572}
6573
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006574bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006575 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006576 Parser.Lex(); // Eat "nodsp".
6577
6578 // If this is not the end of the statement, report an error.
6579 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6580 reportParseError("unexpected token, expected end of statement");
6581 return false;
6582 }
6583
6584 clearFeatureBits(Mips::FeatureDSP, "dsp");
6585 getTargetStreamer().emitDirectiveSetNoDsp();
6586 return false;
6587}
6588
Toma Tabacucc2502d2014-11-04 17:18:07 +00006589bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006590 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006591 Parser.Lex(); // Eat "mips16".
6592
Jack Carter39536722014-01-22 23:08:42 +00006593 // If this is not the end of the statement, report an error.
6594 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006595 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006596 return false;
6597 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006598
6599 setFeatureBits(Mips::FeatureMips16, "mips16");
6600 getTargetStreamer().emitDirectiveSetMips16();
6601 Parser.Lex(); // Consume the EndOfStatement.
6602 return false;
6603}
6604
6605bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006606 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006607 Parser.Lex(); // Eat "nomips16".
6608
6609 // If this is not the end of the statement, report an error.
6610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6611 reportParseError("unexpected token, expected end of statement");
6612 return false;
6613 }
6614
6615 clearFeatureBits(Mips::FeatureMips16, "mips16");
6616 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006617 Parser.Lex(); // Consume the EndOfStatement.
6618 return false;
6619}
6620
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006621bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006622 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006623 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006624 // Line can be: .set fp=32
6625 // .set fp=xx
6626 // .set fp=64
6627 Parser.Lex(); // Eat fp token
6628 AsmToken Tok = Parser.getTok();
6629 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006630 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006631 return false;
6632 }
6633 Parser.Lex(); // Eat '=' token.
6634 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006635
6636 if (!parseFpABIValue(FpAbiVal, ".set"))
6637 return false;
6638
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006639 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006640 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006641 return false;
6642 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006643 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006644 Parser.Lex(); // Consume the EndOfStatement.
6645 return false;
6646}
6647
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006648bool MipsAsmParser::parseSetOddSPRegDirective() {
6649 MCAsmParser &Parser = getParser();
6650
6651 Parser.Lex(); // Eat "oddspreg".
6652 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6653 reportParseError("unexpected token, expected end of statement");
6654 return false;
6655 }
6656
6657 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6658 getTargetStreamer().emitDirectiveSetOddSPReg();
6659 return false;
6660}
6661
6662bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6663 MCAsmParser &Parser = getParser();
6664
6665 Parser.Lex(); // Eat "nooddspreg".
6666 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6667 reportParseError("unexpected token, expected end of statement");
6668 return false;
6669 }
6670
6671 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6672 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6673 return false;
6674}
6675
Simon Dardis805f1e02017-07-11 21:28:36 +00006676bool MipsAsmParser::parseSetMtDirective() {
6677 MCAsmParser &Parser = getParser();
6678 Parser.Lex(); // Eat "mt".
6679
6680 // If this is not the end of the statement, report an error.
6681 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6682 reportParseError("unexpected token, expected end of statement");
6683 return false;
6684 }
6685
6686 setFeatureBits(Mips::FeatureMT, "mt");
6687 getTargetStreamer().emitDirectiveSetMt();
6688 Parser.Lex(); // Consume the EndOfStatement.
6689 return false;
6690}
6691
6692bool MipsAsmParser::parseSetNoMtDirective() {
6693 MCAsmParser &Parser = getParser();
6694 Parser.Lex(); // Eat "nomt".
6695
6696 // If this is not the end of the statement, report an error.
6697 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6698 reportParseError("unexpected token, expected end of statement");
6699 return false;
6700 }
6701
6702 clearFeatureBits(Mips::FeatureMT, "mt");
6703
6704 getTargetStreamer().emitDirectiveSetNoMt();
6705 Parser.Lex(); // Consume the EndOfStatement.
6706 return false;
6707}
6708
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006709bool MipsAsmParser::parseSetNoCRCDirective() {
6710 MCAsmParser &Parser = getParser();
6711 Parser.Lex(); // Eat "nocrc".
6712
6713 // If this is not the end of the statement, report an error.
6714 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6715 reportParseError("unexpected token, expected end of statement");
6716 return false;
6717 }
6718
6719 clearFeatureBits(Mips::FeatureCRC, "crc");
6720
6721 getTargetStreamer().emitDirectiveSetNoCRC();
6722 Parser.Lex(); // Consume the EndOfStatement.
6723 return false;
6724}
6725
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006726bool MipsAsmParser::parseSetNoVirtDirective() {
6727 MCAsmParser &Parser = getParser();
6728 Parser.Lex(); // Eat "novirt".
6729
6730 // If this is not the end of the statement, report an error.
6731 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6732 reportParseError("unexpected token, expected end of statement");
6733 return false;
6734 }
6735
6736 clearFeatureBits(Mips::FeatureVirt, "virt");
6737
6738 getTargetStreamer().emitDirectiveSetNoVirt();
6739 Parser.Lex(); // Consume the EndOfStatement.
6740 return false;
6741}
6742
Toma Tabacu9db22db2014-09-09 10:15:38 +00006743bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006744 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006745 SMLoc Loc = getLexer().getLoc();
6746
6747 Parser.Lex();
6748 if (getLexer().isNot(AsmToken::EndOfStatement))
6749 return reportParseError("unexpected token, expected end of statement");
6750
6751 // Always keep an element on the options "stack" to prevent the user
6752 // from changing the initial options. This is how we remember them.
6753 if (AssemblerOptions.size() == 2)
6754 return reportParseError(Loc, ".set pop with no .set push");
6755
Akira Hatanakab11ef082015-11-14 06:35:56 +00006756 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006757 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006758 setAvailableFeatures(
6759 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6760 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006761
6762 getTargetStreamer().emitDirectiveSetPop();
6763 return false;
6764}
6765
6766bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006767 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006768 Parser.Lex();
6769 if (getLexer().isNot(AsmToken::EndOfStatement))
6770 return reportParseError("unexpected token, expected end of statement");
6771
6772 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006773 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006774 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006775
6776 getTargetStreamer().emitDirectiveSetPush();
6777 return false;
6778}
6779
Toma Tabacu29696502015-06-02 09:48:04 +00006780bool MipsAsmParser::parseSetSoftFloatDirective() {
6781 MCAsmParser &Parser = getParser();
6782 Parser.Lex();
6783 if (getLexer().isNot(AsmToken::EndOfStatement))
6784 return reportParseError("unexpected token, expected end of statement");
6785
6786 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6787 getTargetStreamer().emitDirectiveSetSoftFloat();
6788 return false;
6789}
6790
6791bool MipsAsmParser::parseSetHardFloatDirective() {
6792 MCAsmParser &Parser = getParser();
6793 Parser.Lex();
6794 if (getLexer().isNot(AsmToken::EndOfStatement))
6795 return reportParseError("unexpected token, expected end of statement");
6796
6797 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6798 getTargetStreamer().emitDirectiveSetHardFloat();
6799 return false;
6800}
6801
Jack Carterd76b2372013-03-21 21:44:16 +00006802bool MipsAsmParser::parseSetAssignment() {
6803 StringRef Name;
6804 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006805 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006806
6807 if (Parser.parseIdentifier(Name))
6808 reportParseError("expected identifier after .set");
6809
6810 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006811 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006812 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006813
Jack Carter3b2c96e2014-01-22 23:31:38 +00006814 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006815 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006816
Jim Grosbach6f482002015-05-18 18:43:14 +00006817 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006818 Sym->setVariableValue(Value);
6819
6820 return false;
6821}
Jack Carterd0bd6422013-04-18 00:41:53 +00006822
Toma Tabacu26647792014-09-09 12:52:14 +00006823bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006824 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006825 Parser.Lex();
6826 if (getLexer().isNot(AsmToken::EndOfStatement))
6827 return reportParseError("unexpected token, expected end of statement");
6828
6829 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006830 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006831 setAvailableFeatures(
6832 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6833 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006834 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6835
6836 getTargetStreamer().emitDirectiveSetMips0();
6837 return false;
6838}
6839
Toma Tabacu85618b32014-08-19 14:22:52 +00006840bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006841 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006842 Parser.Lex();
6843 if (getLexer().isNot(AsmToken::Equal))
6844 return reportParseError("unexpected token, expected equals sign");
6845
6846 Parser.Lex();
6847 StringRef Arch;
6848 if (Parser.parseIdentifier(Arch))
6849 return reportParseError("expected arch identifier");
6850
6851 StringRef ArchFeatureName =
6852 StringSwitch<StringRef>(Arch)
6853 .Case("mips1", "mips1")
6854 .Case("mips2", "mips2")
6855 .Case("mips3", "mips3")
6856 .Case("mips4", "mips4")
6857 .Case("mips5", "mips5")
6858 .Case("mips32", "mips32")
6859 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006860 .Case("mips32r3", "mips32r3")
6861 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006862 .Case("mips32r6", "mips32r6")
6863 .Case("mips64", "mips64")
6864 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006865 .Case("mips64r3", "mips64r3")
6866 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006867 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006868 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006869 .Case("r4000", "mips3") // This is an implementation of Mips3.
6870 .Default("");
6871
6872 if (ArchFeatureName.empty())
6873 return reportParseError("unsupported architecture");
6874
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006875 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6876 return reportParseError("mips64r6 does not support microMIPS");
6877
Toma Tabacu85618b32014-08-19 14:22:52 +00006878 selectArch(ArchFeatureName);
6879 getTargetStreamer().emitDirectiveSetArch(Arch);
6880 return false;
6881}
6882
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006883bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006884 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006885 Parser.Lex();
6886 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006887 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006888
Matheus Almeida2852af82014-04-22 10:15:54 +00006889 switch (Feature) {
6890 default:
6891 llvm_unreachable("Unimplemented feature");
6892 case Mips::FeatureDSP:
6893 setFeatureBits(Mips::FeatureDSP, "dsp");
6894 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006895 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006896 case Mips::FeatureDSPR2:
6897 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6898 getTargetStreamer().emitDirectiveSetDspr2();
6899 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006900 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006901 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006902 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006903 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006904 case Mips::FeatureMips1:
6905 selectArch("mips1");
6906 getTargetStreamer().emitDirectiveSetMips1();
6907 break;
6908 case Mips::FeatureMips2:
6909 selectArch("mips2");
6910 getTargetStreamer().emitDirectiveSetMips2();
6911 break;
6912 case Mips::FeatureMips3:
6913 selectArch("mips3");
6914 getTargetStreamer().emitDirectiveSetMips3();
6915 break;
6916 case Mips::FeatureMips4:
6917 selectArch("mips4");
6918 getTargetStreamer().emitDirectiveSetMips4();
6919 break;
6920 case Mips::FeatureMips5:
6921 selectArch("mips5");
6922 getTargetStreamer().emitDirectiveSetMips5();
6923 break;
6924 case Mips::FeatureMips32:
6925 selectArch("mips32");
6926 getTargetStreamer().emitDirectiveSetMips32();
6927 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006928 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006929 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006930 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006931 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006932 case Mips::FeatureMips32r3:
6933 selectArch("mips32r3");
6934 getTargetStreamer().emitDirectiveSetMips32R3();
6935 break;
6936 case Mips::FeatureMips32r5:
6937 selectArch("mips32r5");
6938 getTargetStreamer().emitDirectiveSetMips32R5();
6939 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006940 case Mips::FeatureMips32r6:
6941 selectArch("mips32r6");
6942 getTargetStreamer().emitDirectiveSetMips32R6();
6943 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006944 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006945 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006946 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006947 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006948 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006949 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006950 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006951 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006952 case Mips::FeatureMips64r3:
6953 selectArch("mips64r3");
6954 getTargetStreamer().emitDirectiveSetMips64R3();
6955 break;
6956 case Mips::FeatureMips64r5:
6957 selectArch("mips64r5");
6958 getTargetStreamer().emitDirectiveSetMips64R5();
6959 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006960 case Mips::FeatureMips64r6:
6961 selectArch("mips64r6");
6962 getTargetStreamer().emitDirectiveSetMips64R6();
6963 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006964 case Mips::FeatureCRC:
6965 setFeatureBits(Mips::FeatureCRC, "crc");
6966 getTargetStreamer().emitDirectiveSetCRC();
6967 break;
Petar Jovanovicd4349f32018-04-27 09:12:08 +00006968 case Mips::FeatureVirt:
6969 setFeatureBits(Mips::FeatureVirt, "virt");
6970 getTargetStreamer().emitDirectiveSetVirt();
6971 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006972 }
6973 return false;
6974}
6975
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006976bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006977 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006978 if (getLexer().isNot(AsmToken::Comma)) {
6979 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006980 return Error(Loc, ErrorStr);
6981 }
6982
Matheus Almeida2852af82014-04-22 10:15:54 +00006983 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006984 return true;
6985}
6986
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006987// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6988// In this class, it is only used for .cprestore.
6989// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6990// MipsTargetELFStreamer and MipsAsmParser.
6991bool MipsAsmParser::isPicAndNotNxxAbi() {
6992 return inPicMode() && !(isABI_N32() || isABI_N64());
6993}
6994
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006995bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006996 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006997 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006998
Toma Tabacudde4c462014-11-06 10:02:45 +00006999 if (inMips16Mode()) {
7000 reportParseError(".cpload is not supported in Mips16 mode");
7001 return false;
7002 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007003
David Blaikie960ea3f2014-06-08 16:18:35 +00007004 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00007005 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007006 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7007 reportParseError("expected register containing function address");
7008 return false;
7009 }
7010
David Blaikie960ea3f2014-06-08 16:18:35 +00007011 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
7012 if (!RegOpnd.isGPRAsmReg()) {
7013 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007014 return false;
7015 }
7016
Toma Tabacudde4c462014-11-06 10:02:45 +00007017 // If this is not the end of the statement, report an error.
7018 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7019 reportParseError("unexpected token, expected end of statement");
7020 return false;
7021 }
7022
Toma Tabacuc4c202a2014-10-01 14:53:19 +00007023 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00007024 return false;
7025}
7026
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007027bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
7028 MCAsmParser &Parser = getParser();
7029
7030 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
7031 // is used in non-PIC mode.
7032
7033 if (inMips16Mode()) {
7034 reportParseError(".cprestore is not supported in Mips16 mode");
7035 return false;
7036 }
7037
7038 // Get the stack offset value.
7039 const MCExpr *StackOffset;
7040 int64_t StackOffsetVal;
7041 if (Parser.parseExpression(StackOffset)) {
7042 reportParseError("expected stack offset value");
7043 return false;
7044 }
7045
7046 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
7047 reportParseError("stack offset is not an absolute expression");
7048 return false;
7049 }
7050
7051 if (StackOffsetVal < 0) {
7052 Warning(Loc, ".cprestore with negative stack offset has no effect");
7053 IsCpRestoreSet = false;
7054 } else {
7055 IsCpRestoreSet = true;
7056 CpRestoreOffset = StackOffsetVal;
7057 }
7058
7059 // If this is not the end of the statement, report an error.
7060 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7061 reportParseError("unexpected token, expected end of statement");
7062 return false;
7063 }
7064
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007065 if (!getTargetStreamer().emitDirectiveCpRestore(
7066 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007067 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007068 Parser.Lex(); // Consume the EndOfStatement.
7069 return false;
7070}
7071
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007072bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007073 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007074 unsigned FuncReg;
7075 unsigned Save;
7076 bool SaveIsReg = true;
7077
Matheus Almeida7e815762014-06-18 13:08:59 +00007078 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007079 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007080 if (ResTy == MatchOperand_NoMatch) {
7081 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007082 return false;
7083 }
7084
7085 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7086 if (!FuncRegOpnd.isGPRAsmReg()) {
7087 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007088 return false;
7089 }
7090
7091 FuncReg = FuncRegOpnd.getGPR32Reg();
7092 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007093
Toma Tabacu65f10572014-09-16 15:00:52 +00007094 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007095 return true;
7096
Toma Tabacu13964452014-09-04 13:23:44 +00007097 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007098 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007099 const MCExpr *OffsetExpr;
7100 int64_t OffsetVal;
7101 SMLoc ExprLoc = getLexer().getLoc();
7102
7103 if (Parser.parseExpression(OffsetExpr) ||
7104 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7105 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007106 return false;
7107 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007108
7109 Save = OffsetVal;
7110 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007111 } else {
7112 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7113 if (!SaveOpnd.isGPRAsmReg()) {
7114 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007115 return false;
7116 }
7117 Save = SaveOpnd.getGPR32Reg();
7118 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007119
Toma Tabacu65f10572014-09-16 15:00:52 +00007120 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007121 return true;
7122
Toma Tabacu8874eac2015-02-18 13:46:53 +00007123 const MCExpr *Expr;
7124 if (Parser.parseExpression(Expr)) {
7125 reportParseError("expected expression");
7126 return false;
7127 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007128
Toma Tabacu8874eac2015-02-18 13:46:53 +00007129 if (Expr->getKind() != MCExpr::SymbolRef) {
7130 reportParseError("expected symbol");
7131 return false;
7132 }
7133 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7134
Daniel Sandersf173dda2015-09-22 10:50:09 +00007135 CpSaveLocation = Save;
7136 CpSaveLocationIsRegister = SaveIsReg;
7137
Toma Tabacu8874eac2015-02-18 13:46:53 +00007138 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7139 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007140 return false;
7141}
7142
Daniel Sandersf173dda2015-09-22 10:50:09 +00007143bool MipsAsmParser::parseDirectiveCPReturn() {
7144 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7145 CpSaveLocationIsRegister);
7146 return false;
7147}
7148
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007149bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007150 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007151 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7152 const AsmToken &Tok = Parser.getTok();
7153
7154 if (Tok.getString() == "2008") {
7155 Parser.Lex();
7156 getTargetStreamer().emitDirectiveNaN2008();
7157 return false;
7158 } else if (Tok.getString() == "legacy") {
7159 Parser.Lex();
7160 getTargetStreamer().emitDirectiveNaNLegacy();
7161 return false;
7162 }
7163 }
7164 // If we don't recognize the option passed to the .nan
7165 // directive (e.g. no option or unknown option), emit an error.
7166 reportParseError("invalid option in .nan directive");
7167 return false;
7168}
7169
Jack Carter0b744b32012-10-04 02:29:46 +00007170bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007171 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00007172 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00007173 const AsmToken &Tok = Parser.getTok();
7174
7175 if (Tok.getString() == "noat") {
7176 return parseSetNoAtDirective();
7177 } else if (Tok.getString() == "at") {
7178 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00007179 } else if (Tok.getString() == "arch") {
7180 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00007181 } else if (Tok.getString() == "bopt") {
7182 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
7183 getParser().Lex();
7184 return false;
7185 } else if (Tok.getString() == "nobopt") {
7186 // We're already running in nobopt mode, so nothing to do.
7187 getParser().Lex();
7188 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007189 } else if (Tok.getString() == "fp") {
7190 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007191 } else if (Tok.getString() == "oddspreg") {
7192 return parseSetOddSPRegDirective();
7193 } else if (Tok.getString() == "nooddspreg") {
7194 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00007195 } else if (Tok.getString() == "pop") {
7196 return parseSetPopDirective();
7197 } else if (Tok.getString() == "push") {
7198 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00007199 } else if (Tok.getString() == "reorder") {
7200 return parseSetReorderDirective();
7201 } else if (Tok.getString() == "noreorder") {
7202 return parseSetNoReorderDirective();
7203 } else if (Tok.getString() == "macro") {
7204 return parseSetMacroDirective();
7205 } else if (Tok.getString() == "nomacro") {
7206 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00007207 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00007208 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007209 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00007210 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007211 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007212 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007213 getTargetStreamer().emitDirectiveSetNoMicroMips();
7214 Parser.eatToEndOfStatement();
7215 return false;
7216 } else if (Tok.getString() == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007217 if (hasMips64r6()) {
7218 Error(Tok.getLoc(), ".set micromips directive is not supported with MIPS64R6");
7219 return false;
7220 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007221 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00007222 } else if (Tok.getString() == "mips0") {
7223 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00007224 } else if (Tok.getString() == "mips1") {
7225 return parseSetFeature(Mips::FeatureMips1);
7226 } else if (Tok.getString() == "mips2") {
7227 return parseSetFeature(Mips::FeatureMips2);
7228 } else if (Tok.getString() == "mips3") {
7229 return parseSetFeature(Mips::FeatureMips3);
7230 } else if (Tok.getString() == "mips4") {
7231 return parseSetFeature(Mips::FeatureMips4);
7232 } else if (Tok.getString() == "mips5") {
7233 return parseSetFeature(Mips::FeatureMips5);
7234 } else if (Tok.getString() == "mips32") {
7235 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00007236 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007237 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007238 } else if (Tok.getString() == "mips32r3") {
7239 return parseSetFeature(Mips::FeatureMips32r3);
7240 } else if (Tok.getString() == "mips32r5") {
7241 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007242 } else if (Tok.getString() == "mips32r6") {
7243 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007244 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007245 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007246 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007247 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007248 } else if (Tok.getString() == "mips64r3") {
7249 return parseSetFeature(Mips::FeatureMips64r3);
7250 } else if (Tok.getString() == "mips64r5") {
7251 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007252 } else if (Tok.getString() == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007253 if (inMicroMipsMode()) {
7254 Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS");
7255 return false;
7256 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007257 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00007258 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007259 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00007260 } else if (Tok.getString() == "dspr2") {
7261 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00007262 } else if (Tok.getString() == "nodsp") {
7263 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00007264 } else if (Tok.getString() == "msa") {
7265 return parseSetMsaDirective();
7266 } else if (Tok.getString() == "nomsa") {
7267 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00007268 } else if (Tok.getString() == "mt") {
7269 return parseSetMtDirective();
7270 } else if (Tok.getString() == "nomt") {
7271 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00007272 } else if (Tok.getString() == "softfloat") {
7273 return parseSetSoftFloatDirective();
7274 } else if (Tok.getString() == "hardfloat") {
7275 return parseSetHardFloatDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007276 } else if (Tok.getString() == "crc") {
7277 return parseSetFeature(Mips::FeatureCRC);
7278 } else if (Tok.getString() == "nocrc") {
7279 return parseSetNoCRCDirective();
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007280 } else if (Tok.getString() == "virt") {
7281 return parseSetFeature(Mips::FeatureVirt);
7282 } else if (Tok.getString() == "novirt") {
7283 return parseSetNoVirtDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00007284 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00007285 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00007286 parseSetAssignment();
7287 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00007288 }
Jack Carter07c818d2013-01-25 01:31:34 +00007289
Jack Carter0b744b32012-10-04 02:29:46 +00007290 return true;
7291}
7292
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007293/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007294/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007295bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007296 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007298 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007299 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007300 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007301 return true;
7302
7303 getParser().getStreamer().EmitValue(Value, Size);
7304
7305 if (getLexer().is(AsmToken::EndOfStatement))
7306 break;
7307
Jack Carter07c818d2013-01-25 01:31:34 +00007308 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007309 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007310 Parser.Lex();
7311 }
7312 }
7313
7314 Parser.Lex();
7315 return false;
7316}
7317
Vladimir Medic4c299852013-11-06 11:27:05 +00007318/// parseDirectiveGpWord
7319/// ::= .gpword local_sym
7320bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007321 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007322 const MCExpr *Value;
7323 // EmitGPRel32Value requires an expression, so we are using base class
7324 // method to evaluate the expression.
7325 if (getParser().parseExpression(Value))
7326 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007327 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007328
Vladimir Medice10c1122013-11-13 13:18:04 +00007329 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007330 return Error(getLexer().getLoc(),
7331 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007332 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007333 return false;
7334}
7335
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007336/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007337/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007338bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007339 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007340 const MCExpr *Value;
7341 // EmitGPRel64Value requires an expression, so we are using base class
7342 // method to evaluate the expression.
7343 if (getParser().parseExpression(Value))
7344 return true;
7345 getParser().getStreamer().EmitGPRel64Value(Value);
7346
7347 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007348 return Error(getLexer().getLoc(),
7349 "unexpected token, expected end of statement");
7350 Parser.Lex(); // Eat EndOfStatement token.
7351 return false;
7352}
7353
7354/// parseDirectiveDtpRelWord
7355/// ::= .dtprelword tls_sym
7356bool MipsAsmParser::parseDirectiveDtpRelWord() {
7357 MCAsmParser &Parser = getParser();
7358 const MCExpr *Value;
7359 // EmitDTPRel32Value requires an expression, so we are using base class
7360 // method to evaluate the expression.
7361 if (getParser().parseExpression(Value))
7362 return true;
7363 getParser().getStreamer().EmitDTPRel32Value(Value);
7364
7365 if (getLexer().isNot(AsmToken::EndOfStatement))
7366 return Error(getLexer().getLoc(),
7367 "unexpected token, expected end of statement");
7368 Parser.Lex(); // Eat EndOfStatement token.
7369 return false;
7370}
7371
7372/// parseDirectiveDtpRelDWord
7373/// ::= .dtpreldword tls_sym
7374bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7375 MCAsmParser &Parser = getParser();
7376 const MCExpr *Value;
7377 // EmitDTPRel64Value requires an expression, so we are using base class
7378 // method to evaluate the expression.
7379 if (getParser().parseExpression(Value))
7380 return true;
7381 getParser().getStreamer().EmitDTPRel64Value(Value);
7382
7383 if (getLexer().isNot(AsmToken::EndOfStatement))
7384 return Error(getLexer().getLoc(),
7385 "unexpected token, expected end of statement");
7386 Parser.Lex(); // Eat EndOfStatement token.
7387 return false;
7388}
7389
7390/// parseDirectiveTpRelWord
7391/// ::= .tprelword tls_sym
7392bool MipsAsmParser::parseDirectiveTpRelWord() {
7393 MCAsmParser &Parser = getParser();
7394 const MCExpr *Value;
7395 // EmitTPRel32Value requires an expression, so we are using base class
7396 // method to evaluate the expression.
7397 if (getParser().parseExpression(Value))
7398 return true;
7399 getParser().getStreamer().EmitTPRel32Value(Value);
7400
7401 if (getLexer().isNot(AsmToken::EndOfStatement))
7402 return Error(getLexer().getLoc(),
7403 "unexpected token, expected end of statement");
7404 Parser.Lex(); // Eat EndOfStatement token.
7405 return false;
7406}
7407
7408/// parseDirectiveTpRelDWord
7409/// ::= .tpreldword tls_sym
7410bool MipsAsmParser::parseDirectiveTpRelDWord() {
7411 MCAsmParser &Parser = getParser();
7412 const MCExpr *Value;
7413 // EmitTPRel64Value requires an expression, so we are using base class
7414 // method to evaluate the expression.
7415 if (getParser().parseExpression(Value))
7416 return true;
7417 getParser().getStreamer().EmitTPRel64Value(Value);
7418
7419 if (getLexer().isNot(AsmToken::EndOfStatement))
7420 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007421 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007422 Parser.Lex(); // Eat EndOfStatement token.
7423 return false;
7424}
7425
Jack Carter0cd3c192014-01-06 23:27:31 +00007426bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007427 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007428 // Get the option token.
7429 AsmToken Tok = Parser.getTok();
7430 // At the moment only identifiers are supported.
7431 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007432 return Error(Parser.getTok().getLoc(),
7433 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007434 }
7435
7436 StringRef Option = Tok.getIdentifier();
7437
7438 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007439 // MipsAsmParser needs to know if the current PIC mode changes.
7440 IsPicEnabled = false;
7441
Jack Carter0cd3c192014-01-06 23:27:31 +00007442 getTargetStreamer().emitDirectiveOptionPic0();
7443 Parser.Lex();
7444 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007445 return Error(Parser.getTok().getLoc(),
7446 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007447 }
7448 return false;
7449 }
7450
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007451 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007452 // MipsAsmParser needs to know if the current PIC mode changes.
7453 IsPicEnabled = true;
7454
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007455 getTargetStreamer().emitDirectiveOptionPic2();
7456 Parser.Lex();
7457 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007458 return Error(Parser.getTok().getLoc(),
7459 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007460 }
7461 return false;
7462 }
7463
Jack Carter0cd3c192014-01-06 23:27:31 +00007464 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007465 Warning(Parser.getTok().getLoc(),
7466 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007467 Parser.eatToEndOfStatement();
7468 return false;
7469}
7470
Toma Tabacu9ca50962015-04-16 09:53:47 +00007471/// parseInsnDirective
7472/// ::= .insn
7473bool MipsAsmParser::parseInsnDirective() {
7474 // If this is not the end of the statement, report an error.
7475 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7476 reportParseError("unexpected token, expected end of statement");
7477 return false;
7478 }
7479
7480 // The actual label marking happens in
7481 // MipsELFStreamer::createPendingLabelRelocs().
7482 getTargetStreamer().emitDirectiveInsn();
7483
7484 getParser().Lex(); // Eat EndOfStatement token.
7485 return false;
7486}
7487
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007488/// parseRSectionDirective
7489/// ::= .rdata
7490bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7491 // If this is not the end of the statement, report an error.
7492 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7493 reportParseError("unexpected token, expected end of statement");
7494 return false;
7495 }
7496
7497 MCSection *ELFSection = getContext().getELFSection(
7498 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7499 getParser().getStreamer().SwitchSection(ELFSection);
7500
7501 getParser().Lex(); // Eat EndOfStatement token.
7502 return false;
7503}
7504
Simon Atanasyanbe186202016-02-11 06:45:54 +00007505/// parseSSectionDirective
7506/// ::= .sbss
7507/// ::= .sdata
7508bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7509 // If this is not the end of the statement, report an error.
7510 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7511 reportParseError("unexpected token, expected end of statement");
7512 return false;
7513 }
7514
7515 MCSection *ELFSection = getContext().getELFSection(
7516 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7517 getParser().getStreamer().SwitchSection(ELFSection);
7518
7519 getParser().Lex(); // Eat EndOfStatement token.
7520 return false;
7521}
7522
Daniel Sanders7e527422014-07-10 13:38:23 +00007523/// parseDirectiveModule
7524/// ::= .module oddspreg
7525/// ::= .module nooddspreg
7526/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007527/// ::= .module softfloat
7528/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007529/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007530/// ::= .module crc
7531/// ::= .module nocrc
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007532/// ::= .module virt
7533/// ::= .module novirt
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007534bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007535 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007536 MCAsmLexer &Lexer = getLexer();
7537 SMLoc L = Lexer.getLoc();
7538
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007539 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007540 // TODO : get a better message.
7541 reportParseError(".module directive must appear before any code");
7542 return false;
7543 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007544
Toma Tabacuc405c822015-01-23 10:40:19 +00007545 StringRef Option;
7546 if (Parser.parseIdentifier(Option)) {
7547 reportParseError("expected .module option identifier");
7548 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007549 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007550
Toma Tabacuc405c822015-01-23 10:40:19 +00007551 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007552 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007553
Toma Tabacu3c499582015-06-25 10:56:57 +00007554 // Synchronize the abiflags information with the FeatureBits information we
7555 // changed above.
7556 getTargetStreamer().updateABIInfo(*this);
7557
7558 // If printing assembly, use the recently updated abiflags information.
7559 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7560 // emitted at the end).
7561 getTargetStreamer().emitDirectiveModuleOddSPReg();
7562
Toma Tabacuc405c822015-01-23 10:40:19 +00007563 // If this is not the end of the statement, report an error.
7564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7565 reportParseError("unexpected token, expected end of statement");
7566 return false;
7567 }
7568
7569 return false; // parseDirectiveModule has finished successfully.
7570 } else if (Option == "nooddspreg") {
7571 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007572 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007573 }
7574
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007575 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007576
Toma Tabacu3c499582015-06-25 10:56:57 +00007577 // Synchronize the abiflags information with the FeatureBits information we
7578 // changed above.
7579 getTargetStreamer().updateABIInfo(*this);
7580
7581 // If printing assembly, use the recently updated abiflags information.
7582 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7583 // emitted at the end).
7584 getTargetStreamer().emitDirectiveModuleOddSPReg();
7585
Toma Tabacuc405c822015-01-23 10:40:19 +00007586 // If this is not the end of the statement, report an error.
7587 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7588 reportParseError("unexpected token, expected end of statement");
7589 return false;
7590 }
7591
7592 return false; // parseDirectiveModule has finished successfully.
7593 } else if (Option == "fp") {
7594 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007595 } else if (Option == "softfloat") {
7596 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7597
7598 // Synchronize the ABI Flags information with the FeatureBits information we
7599 // updated above.
7600 getTargetStreamer().updateABIInfo(*this);
7601
7602 // If printing assembly, use the recently updated ABI Flags information.
7603 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7604 // emitted later).
7605 getTargetStreamer().emitDirectiveModuleSoftFloat();
7606
7607 // If this is not the end of the statement, report an error.
7608 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7609 reportParseError("unexpected token, expected end of statement");
7610 return false;
7611 }
7612
7613 return false; // parseDirectiveModule has finished successfully.
7614 } else if (Option == "hardfloat") {
7615 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7616
7617 // Synchronize the ABI Flags information with the FeatureBits information we
7618 // updated above.
7619 getTargetStreamer().updateABIInfo(*this);
7620
7621 // If printing assembly, use the recently updated ABI Flags information.
7622 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7623 // emitted later).
7624 getTargetStreamer().emitDirectiveModuleHardFloat();
7625
7626 // If this is not the end of the statement, report an error.
7627 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7628 reportParseError("unexpected token, expected end of statement");
7629 return false;
7630 }
7631
7632 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007633 } else if (Option == "mt") {
7634 setModuleFeatureBits(Mips::FeatureMT, "mt");
7635
7636 // Synchronize the ABI Flags information with the FeatureBits information we
7637 // updated above.
7638 getTargetStreamer().updateABIInfo(*this);
7639
Simon Dardisd9611922017-07-11 21:36:58 +00007640 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007641 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7642 // emitted later).
7643 getTargetStreamer().emitDirectiveModuleMT();
7644
7645 // If this is not the end of the statement, report an error.
7646 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7647 reportParseError("unexpected token, expected end of statement");
7648 return false;
7649 }
7650
7651 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007652 } else if (Option == "crc") {
7653 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7654
7655 // Synchronize the ABI Flags information with the FeatureBits information we
7656 // updated above.
7657 getTargetStreamer().updateABIInfo(*this);
7658
7659 // If printing assembly, use the recently updated ABI Flags information.
7660 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7661 // emitted later).
7662 getTargetStreamer().emitDirectiveModuleCRC();
7663
7664 // If this is not the end of the statement, report an error.
7665 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7666 reportParseError("unexpected token, expected end of statement");
7667 return false;
7668 }
7669
7670 return false; // parseDirectiveModule has finished successfully.
7671 } else if (Option == "nocrc") {
7672 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7673
7674 // Synchronize the ABI Flags information with the FeatureBits information we
7675 // updated above.
7676 getTargetStreamer().updateABIInfo(*this);
7677
7678 // If printing assembly, use the recently updated ABI Flags information.
7679 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7680 // emitted later).
7681 getTargetStreamer().emitDirectiveModuleNoCRC();
7682
7683 // If this is not the end of the statement, report an error.
7684 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7685 reportParseError("unexpected token, expected end of statement");
7686 return false;
7687 }
7688
7689 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovicd4349f32018-04-27 09:12:08 +00007690 } else if (Option == "virt") {
7691 setModuleFeatureBits(Mips::FeatureVirt, "virt");
7692
7693 // Synchronize the ABI Flags information with the FeatureBits information we
7694 // updated above.
7695 getTargetStreamer().updateABIInfo(*this);
7696
7697 // If printing assembly, use the recently updated ABI Flags information.
7698 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7699 // emitted later).
7700 getTargetStreamer().emitDirectiveModuleVirt();
7701
7702 // If this is not the end of the statement, report an error.
7703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7704 reportParseError("unexpected token, expected end of statement");
7705 return false;
7706 }
7707
7708 return false; // parseDirectiveModule has finished successfully.
7709 } else if (Option == "novirt") {
7710 clearModuleFeatureBits(Mips::FeatureVirt, "virt");
7711
7712 // Synchronize the ABI Flags information with the FeatureBits information we
7713 // updated above.
7714 getTargetStreamer().updateABIInfo(*this);
7715
7716 // If printing assembly, use the recently updated ABI Flags information.
7717 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7718 // emitted later).
7719 getTargetStreamer().emitDirectiveModuleNoVirt();
7720
7721 // If this is not the end of the statement, report an error.
7722 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7723 reportParseError("unexpected token, expected end of statement");
7724 return false;
7725 }
7726
7727 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007728 } else {
7729 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7730 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007731}
7732
7733/// parseDirectiveModuleFP
7734/// ::= =32
7735/// ::= =xx
7736/// ::= =64
7737bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007738 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007739 MCAsmLexer &Lexer = getLexer();
7740
7741 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007742 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007743 return false;
7744 }
7745 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007746
Daniel Sanders7e527422014-07-10 13:38:23 +00007747 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007748 if (!parseFpABIValue(FpABI, ".module"))
7749 return false;
7750
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007751 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007752 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007753 return false;
7754 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007755
Toma Tabacua64e5402015-06-25 12:44:38 +00007756 // Synchronize the abiflags information with the FeatureBits information we
7757 // changed above.
7758 getTargetStreamer().updateABIInfo(*this);
7759
7760 // If printing assembly, use the recently updated abiflags information.
7761 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7762 // emitted at the end).
7763 getTargetStreamer().emitDirectiveModuleFP();
7764
Daniel Sanders7e527422014-07-10 13:38:23 +00007765 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007766 return false;
7767}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007768
Daniel Sanders7e527422014-07-10 13:38:23 +00007769bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007770 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007771 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007772 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007773 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007774
7775 if (Lexer.is(AsmToken::Identifier)) {
7776 StringRef Value = Parser.getTok().getString();
7777 Parser.Lex();
7778
7779 if (Value != "xx") {
7780 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7781 return false;
7782 }
7783
7784 if (!isABI_O32()) {
7785 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7786 return false;
7787 }
7788
Daniel Sanders7e527422014-07-10 13:38:23 +00007789 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007790 if (ModuleLevelOptions) {
7791 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7792 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7793 } else {
7794 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7795 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7796 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007797 return true;
7798 }
7799
7800 if (Lexer.is(AsmToken::Integer)) {
7801 unsigned Value = Parser.getTok().getIntVal();
7802 Parser.Lex();
7803
7804 if (Value != 32 && Value != 64) {
7805 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7806 return false;
7807 }
7808
7809 if (Value == 32) {
7810 if (!isABI_O32()) {
7811 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7812 return false;
7813 }
7814
Daniel Sanders7e527422014-07-10 13:38:23 +00007815 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007816 if (ModuleLevelOptions) {
7817 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7818 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7819 } else {
7820 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7821 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7822 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007823 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007824 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007825 if (ModuleLevelOptions) {
7826 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7827 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7828 } else {
7829 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7830 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7831 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007832 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007833
Daniel Sanders7e527422014-07-10 13:38:23 +00007834 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007835 }
7836
7837 return false;
7838}
7839
Jack Carter0b744b32012-10-04 02:29:46 +00007840bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007841 // This returns false if this function recognizes the directive
7842 // regardless of whether it is successfully handles or reports an
7843 // error. Otherwise it returns true to give the generic parser a
7844 // chance at recognizing it.
7845
Rafael Espindola961d4692014-11-11 05:18:41 +00007846 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007847 StringRef IDVal = DirectiveID.getString();
7848
Nirav Dave996fc132016-05-05 14:15:46 +00007849 if (IDVal == ".cpload") {
7850 parseDirectiveCpLoad(DirectiveID.getLoc());
7851 return false;
7852 }
7853 if (IDVal == ".cprestore") {
7854 parseDirectiveCpRestore(DirectiveID.getLoc());
7855 return false;
7856 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007857 if (IDVal == ".dword") {
7858 parseDataDirective(8, DirectiveID.getLoc());
7859 return false;
7860 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007861 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007862 StringRef SymbolName;
7863
7864 if (Parser.parseIdentifier(SymbolName)) {
7865 reportParseError("expected identifier after .ent");
7866 return false;
7867 }
7868
7869 // There's an undocumented extension that allows an integer to
7870 // follow the name of the procedure which AFAICS is ignored by GAS.
7871 // Example: .ent foo,2
7872 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7873 if (getLexer().isNot(AsmToken::Comma)) {
7874 // Even though we accept this undocumented extension for compatibility
7875 // reasons, the additional integer argument does not actually change
7876 // the behaviour of the '.ent' directive, so we would like to discourage
7877 // its use. We do this by not referring to the extended version in
7878 // error messages which are not directly related to its use.
7879 reportParseError("unexpected token, expected end of statement");
7880 return false;
7881 }
7882 Parser.Lex(); // Eat the comma.
7883 const MCExpr *DummyNumber;
7884 int64_t DummyNumberVal;
7885 // If the user was explicitly trying to use the extended version,
7886 // we still give helpful extension-related error messages.
7887 if (Parser.parseExpression(DummyNumber)) {
7888 reportParseError("expected number after comma");
7889 return false;
7890 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007891 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007892 reportParseError("expected an absolute expression after comma");
7893 return false;
7894 }
7895 }
7896
7897 // If this is not the end of the statement, report an error.
7898 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7899 reportParseError("unexpected token, expected end of statement");
7900 return false;
7901 }
7902
Jim Grosbach6f482002015-05-18 18:43:14 +00007903 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007904
7905 getTargetStreamer().emitDirectiveEnt(*Sym);
7906 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007907 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007908 return false;
7909 }
7910
Jack Carter07c818d2013-01-25 01:31:34 +00007911 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007912 StringRef SymbolName;
7913
7914 if (Parser.parseIdentifier(SymbolName)) {
7915 reportParseError("expected identifier after .end");
7916 return false;
7917 }
7918
7919 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7920 reportParseError("unexpected token, expected end of statement");
7921 return false;
7922 }
7923
7924 if (CurrentFn == nullptr) {
7925 reportParseError(".end used without .ent");
7926 return false;
7927 }
7928
7929 if ((SymbolName != CurrentFn->getName())) {
7930 reportParseError(".end symbol does not match .ent symbol");
7931 return false;
7932 }
7933
7934 getTargetStreamer().emitDirectiveEnd(SymbolName);
7935 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007936 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007937 return false;
7938 }
7939
Jack Carter07c818d2013-01-25 01:31:34 +00007940 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007941 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7942 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007943 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007944 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7945 reportParseError("expected stack register");
7946 return false;
7947 }
7948
7949 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7950 if (!StackRegOpnd.isGPRAsmReg()) {
7951 reportParseError(StackRegOpnd.getStartLoc(),
7952 "expected general purpose register");
7953 return false;
7954 }
7955 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7956
7957 if (Parser.getTok().is(AsmToken::Comma))
7958 Parser.Lex();
7959 else {
7960 reportParseError("unexpected token, expected comma");
7961 return false;
7962 }
7963
7964 // Parse the frame size.
7965 const MCExpr *FrameSize;
7966 int64_t FrameSizeVal;
7967
7968 if (Parser.parseExpression(FrameSize)) {
7969 reportParseError("expected frame size value");
7970 return false;
7971 }
7972
Jim Grosbach13760bd2015-05-30 01:25:56 +00007973 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007974 reportParseError("frame size not an absolute expression");
7975 return false;
7976 }
7977
7978 if (Parser.getTok().is(AsmToken::Comma))
7979 Parser.Lex();
7980 else {
7981 reportParseError("unexpected token, expected comma");
7982 return false;
7983 }
7984
7985 // Parse the return register.
7986 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007987 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007988 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7989 reportParseError("expected return register");
7990 return false;
7991 }
7992
7993 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7994 if (!ReturnRegOpnd.isGPRAsmReg()) {
7995 reportParseError(ReturnRegOpnd.getStartLoc(),
7996 "expected general purpose register");
7997 return false;
7998 }
7999
8000 // If this is not the end of the statement, report an error.
8001 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8002 reportParseError("unexpected token, expected end of statement");
8003 return false;
8004 }
8005
8006 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
8007 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00008008 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00008009 return false;
8010 }
8011
Jack Carter07c818d2013-01-25 01:31:34 +00008012 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00008013 parseDirectiveSet();
8014 return false;
Jack Carterbe332172012-09-07 00:48:02 +00008015 }
8016
Daniel Sandersd97a6342014-08-13 10:07:34 +00008017 if (IDVal == ".mask" || IDVal == ".fmask") {
8018 // .mask bitmask, frame_offset
8019 // bitmask: One bit for each register used.
8020 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
8021 // first register is expected to be saved.
8022 // Examples:
8023 // .mask 0x80000000, -4
8024 // .fmask 0x80000000, -4
8025 //
Jack Carterbe332172012-09-07 00:48:02 +00008026
Daniel Sandersd97a6342014-08-13 10:07:34 +00008027 // Parse the bitmask
8028 const MCExpr *BitMask;
8029 int64_t BitMaskVal;
8030
8031 if (Parser.parseExpression(BitMask)) {
8032 reportParseError("expected bitmask value");
8033 return false;
8034 }
8035
Jim Grosbach13760bd2015-05-30 01:25:56 +00008036 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008037 reportParseError("bitmask not an absolute expression");
8038 return false;
8039 }
8040
8041 if (Parser.getTok().is(AsmToken::Comma))
8042 Parser.Lex();
8043 else {
8044 reportParseError("unexpected token, expected comma");
8045 return false;
8046 }
8047
8048 // Parse the frame_offset
8049 const MCExpr *FrameOffset;
8050 int64_t FrameOffsetVal;
8051
8052 if (Parser.parseExpression(FrameOffset)) {
8053 reportParseError("expected frame offset value");
8054 return false;
8055 }
8056
Jim Grosbach13760bd2015-05-30 01:25:56 +00008057 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00008058 reportParseError("frame offset not an absolute expression");
8059 return false;
8060 }
8061
8062 // If this is not the end of the statement, report an error.
8063 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8064 reportParseError("unexpected token, expected end of statement");
8065 return false;
8066 }
8067
8068 if (IDVal == ".mask")
8069 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
8070 else
8071 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00008072 return false;
8073 }
8074
Matheus Almeida0051f2d2014-04-16 15:48:55 +00008075 if (IDVal == ".nan")
8076 return parseDirectiveNaN();
8077
Jack Carter07c818d2013-01-25 01:31:34 +00008078 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00008079 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00008080 return false;
8081 }
8082
Rafael Espindolab59fb732014-03-28 18:50:26 +00008083 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00008084 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00008085 return false;
8086 }
8087
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00008088 if (IDVal == ".dtprelword") {
8089 parseDirectiveDtpRelWord();
8090 return false;
8091 }
8092
8093 if (IDVal == ".dtpreldword") {
8094 parseDirectiveDtpRelDWord();
8095 return false;
8096 }
8097
8098 if (IDVal == ".tprelword") {
8099 parseDirectiveTpRelWord();
8100 return false;
8101 }
8102
8103 if (IDVal == ".tpreldword") {
8104 parseDirectiveTpRelDWord();
8105 return false;
8106 }
8107
Jack Carter07c818d2013-01-25 01:31:34 +00008108 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00008109 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00008110 return false;
8111 }
8112
Scott Egertond1aeb052016-02-15 16:11:51 +00008113 if (IDVal == ".hword") {
8114 parseDataDirective(2, DirectiveID.getLoc());
8115 return false;
8116 }
8117
Nirav Dave996fc132016-05-05 14:15:46 +00008118 if (IDVal == ".option") {
8119 parseDirectiveOption();
8120 return false;
8121 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008122
8123 if (IDVal == ".abicalls") {
8124 getTargetStreamer().emitDirectiveAbiCalls();
8125 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00008126 Error(Parser.getTok().getLoc(),
8127 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008128 }
8129 return false;
8130 }
8131
Nirav Dave996fc132016-05-05 14:15:46 +00008132 if (IDVal == ".cpsetup") {
8133 parseDirectiveCPSetup();
8134 return false;
8135 }
8136 if (IDVal == ".cpreturn") {
8137 parseDirectiveCPReturn();
8138 return false;
8139 }
8140 if (IDVal == ".module") {
8141 parseDirectiveModule();
8142 return false;
8143 }
8144 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8145 parseInternalDirectiveReallowModule();
8146 return false;
8147 }
8148 if (IDVal == ".insn") {
8149 parseInsnDirective();
8150 return false;
8151 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008152 if (IDVal == ".rdata") {
8153 parseRSectionDirective(".rodata");
8154 return false;
8155 }
Nirav Dave996fc132016-05-05 14:15:46 +00008156 if (IDVal == ".sbss") {
8157 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8158 return false;
8159 }
8160 if (IDVal == ".sdata") {
8161 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8162 return false;
8163 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008164
Rafael Espindola870c4e92012-01-11 03:56:41 +00008165 return true;
8166}
8167
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008168bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8169 // If this is not the end of the statement, report an error.
8170 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8171 reportParseError("unexpected token, expected end of statement");
8172 return false;
8173 }
8174
8175 getTargetStreamer().reallowModuleDirective();
8176
8177 getParser().Lex(); // Eat EndOfStatement token.
8178 return false;
8179}
8180
Rafael Espindola870c4e92012-01-11 03:56:41 +00008181extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008182 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8183 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8184 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8185 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008186}
Jack Carterb4dbc172012-09-05 23:34:03 +00008187
8188#define GET_REGISTER_MATCHER
8189#define GET_MATCHER_IMPLEMENTATION
8190#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008191
8192bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8193 // Find the appropriate table for this asm variant.
8194 const MatchEntry *Start, *End;
8195 switch (VariantID) {
8196 default: llvm_unreachable("invalid variant!");
8197 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8198 }
8199 // Search the table.
8200 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8201 return MnemonicRange.first != MnemonicRange.second;
8202}