blob: f978f8cc7fdf2a5f3f36ede9da551ddb70d806c2 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000307 bool reportParseError(Twine ErrorMsg);
308 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000309
Jack Carterb5cf5902013-04-17 00:18:04 +0000310 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000311
312 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000313 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000314 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000315 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000316 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000317 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000318 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000319 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000320 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000321 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000322 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000323 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000324 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000325 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000326 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000327
328 bool parseSetAtDirective();
329 bool parseSetNoAtDirective();
330 bool parseSetMacroDirective();
331 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000332 bool parseSetMsaDirective();
333 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000334 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000335 bool parseSetReorderDirective();
336 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000337 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000338 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000339 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000340 bool parseSetOddSPRegDirective();
341 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000342 bool parseSetPopDirective();
343 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000344 bool parseSetSoftFloatDirective();
345 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000346
Jack Carterd76b2372013-03-21 21:44:16 +0000347 bool parseSetAssignment();
348
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000349 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000350 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000351 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000352 bool parseDirectiveDtpRelWord();
353 bool parseDirectiveDtpRelDWord();
354 bool parseDirectiveTpRelWord();
355 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000356 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000357 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000358 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
359 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000360
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000361 bool parseInternalDirectiveReallowModule();
362
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000363 bool eatComma(StringRef ErrorStr);
364
Jack Carter1ac53222013-02-20 23:11:17 +0000365 int matchCPURegisterName(StringRef Symbol);
366
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000367 int matchHWRegsRegisterName(StringRef Symbol);
368
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000369 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000370
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000371 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000372
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000373 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000374
Jack Carter5dc8ac92013-09-25 23:50:44 +0000375 int matchMSA128RegisterName(StringRef Name);
376
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000377 int matchMSA128CtrlRegisterName(StringRef Name);
378
Jack Carterd0bd6422013-04-18 00:41:53 +0000379 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000380
Toma Tabacu89a712b2015-04-15 10:48:56 +0000381 /// Returns the internal register number for the current AT. Also checks if
382 /// the current AT is unavailable (set to $0) and gives an error if it is.
383 /// This should be used in pseudo-instruction expansions which need AT.
384 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000385
Simon Dardis3aa8a902017-02-06 12:43:46 +0000386 bool canUseATReg();
387
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000388 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
389 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000390
391 // Helper function that checks if the value of a vector index is within the
392 // boundaries of accepted values for each RegisterKind
393 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
394 bool validateMSAIndex(int Val, int RegKind);
395
Daniel Sandersf0df2212014-08-04 12:20:00 +0000396 // Selects a new architecture by updating the FeatureBits with the necessary
397 // info including implied dependencies.
398 // Internally, it clears all the feature bits related to *any* architecture
399 // and selects the new one using the ToggleFeature functionality of the
400 // MCSubtargetInfo object that handles implied dependencies. The reason we
401 // clear all the arch related bits manually is because ToggleFeature only
402 // clears the features that imply the feature being cleared and not the
403 // features implied by the feature being cleared. This is easier to see
404 // with an example:
405 // --------------------------------------------------
406 // | Feature | Implies |
407 // | -------------------------------------------------|
408 // | FeatureMips1 | None |
409 // | FeatureMips2 | FeatureMips1 |
410 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
411 // | FeatureMips4 | FeatureMips3 |
412 // | ... | |
413 // --------------------------------------------------
414 //
415 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
416 // FeatureMipsGP64 | FeatureMips1)
417 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
418 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000419 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000420 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000421 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
422 STI.setFeatureBits(FeatureBits);
423 setAvailableFeatures(
424 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000425 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000426 }
427
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000428 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000429 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000430 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000431 setAvailableFeatures(
432 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000433 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000434 }
435 }
436
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000437 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000438 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000439 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000440 setAvailableFeatures(
441 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000442 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000443 }
444 }
445
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000446 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
447 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000448 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000449 }
450
451 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
452 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000453 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000454 }
455
Rafael Espindola870c4e92012-01-11 03:56:41 +0000456public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000457 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000458 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000459 Match_RequiresDifferentOperands,
460 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000461 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000462 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000463 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000464#define GET_OPERAND_DIAGNOSTIC_TYPES
465#include "MipsGenAsmMatcher.inc"
466#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000467 };
468
Akira Hatanakab11ef082015-11-14 06:35:56 +0000469 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000472 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
473 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000474 MCAsmParserExtension::Initialize(parser);
475
Toma Tabacu11e14a92015-04-21 11:50:52 +0000476 parser.addAliasForDirective(".asciiz", ".asciz");
477
Jack Carterb4dbc172012-09-05 23:34:03 +0000478 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000479 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000480
Toma Tabacu9db22db2014-09-09 10:15:38 +0000481 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000482 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000483 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000484
Toma Tabacu9db22db2014-09-09 10:15:38 +0000485 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000486 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000488
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000489 getTargetStreamer().updateABIInfo(*this);
490
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000491 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000492 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000493
494 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000495
Rafael Espindola699281c2016-05-18 11:58:50 +0000496 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000497
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000498 IsCpRestoreSet = false;
499 CpRestoreOffset = -1;
500
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000501 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000502 if ((TheTriple.getArch() == Triple::mips) ||
503 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000504 IsLittleEndian = false;
505 else
506 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000507 }
508
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000509 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
510 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
511
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000512 bool isGP64bit() const {
513 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
514 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000515
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 bool isFP64bit() const {
517 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
518 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000519
Eric Christophera5762812015-01-26 17:33:46 +0000520 const MipsABIInfo &getABI() const { return ABI; }
521 bool isABI_N32() const { return ABI.IsN32(); }
522 bool isABI_N64() const { return ABI.IsN64(); }
523 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 bool isABI_FPXX() const {
525 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
526 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000528 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000529 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000530 }
531
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000535
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 bool hasMips1() const {
537 return getSTI().getFeatureBits()[Mips::FeatureMips1];
538 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000539
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 bool hasMips2() const {
541 return getSTI().getFeatureBits()[Mips::FeatureMips2];
542 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000543
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 bool hasMips3() const {
545 return getSTI().getFeatureBits()[Mips::FeatureMips3];
546 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000547
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 bool hasMips4() const {
549 return getSTI().getFeatureBits()[Mips::FeatureMips4];
550 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000551
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 bool hasMips5() const {
553 return getSTI().getFeatureBits()[Mips::FeatureMips5];
554 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000555
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000556 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000558 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000559
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000560 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000562 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000563
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000567
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000568 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000569 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000571
Daniel Sanders17793142015-02-18 16:24:50 +0000572 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000573 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000574 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000575
Daniel Sanders17793142015-02-18 16:24:50 +0000576 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000577 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000578 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000579
Daniel Sanders17793142015-02-18 16:24:50 +0000580 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000581 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000582 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000583
Daniel Sanders17793142015-02-18 16:24:50 +0000584 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000585 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000586 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000587
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000588 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000589 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000591
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000592 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000593 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000594 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000595
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000596 bool hasDSP() const {
597 return getSTI().getFeatureBits()[Mips::FeatureDSP];
598 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000599
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000600 bool hasDSPR2() const {
601 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000603
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000604 bool hasDSPR3() const {
605 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
606 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000607
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000608 bool hasMSA() const {
609 return getSTI().getFeatureBits()[Mips::FeatureMSA];
610 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000611
Kai Nackee0245392015-01-27 19:11:28 +0000612 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000613 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000614 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000615
Daniel Sandersa6994442015-08-18 12:33:54 +0000616 bool inPicMode() {
617 return IsPicEnabled;
618 }
619
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000620 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000621 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000622 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000623
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000624 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000625 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000626 }
627
Eric Christophere8ae3e32015-05-07 23:10:21 +0000628 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000629 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000630 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000631
Toma Tabacud9d344b2015-04-27 14:05:04 +0000632 /// Warn if RegIndex is the same as the current AT.
633 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000634
635 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000636
637 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000638
639 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
640 AsmToken::TokenKind OperatorToken,
641 MCContext &Ctx) override {
642 switch(OperatorToken) {
643 default:
644 llvm_unreachable("Unknown token");
645 return nullptr;
646 case AsmToken::PercentCall16:
647 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
648 case AsmToken::PercentCall_Hi:
649 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
650 case AsmToken::PercentCall_Lo:
651 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
652 case AsmToken::PercentDtprel_Hi:
653 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
654 case AsmToken::PercentDtprel_Lo:
655 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
656 case AsmToken::PercentGot:
657 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
658 case AsmToken::PercentGot_Disp:
659 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
660 case AsmToken::PercentGot_Hi:
661 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
662 case AsmToken::PercentGot_Lo:
663 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
664 case AsmToken::PercentGot_Ofst:
665 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
666 case AsmToken::PercentGot_Page:
667 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
668 case AsmToken::PercentGottprel:
669 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
670 case AsmToken::PercentGp_Rel:
671 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
672 case AsmToken::PercentHi:
673 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
674 case AsmToken::PercentHigher:
675 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
676 case AsmToken::PercentHighest:
677 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
678 case AsmToken::PercentLo:
679 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
680 case AsmToken::PercentNeg:
681 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
682 case AsmToken::PercentPcrel_Hi:
683 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
684 case AsmToken::PercentPcrel_Lo:
685 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
686 case AsmToken::PercentTlsgd:
687 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
688 case AsmToken::PercentTlsldm:
689 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
690 case AsmToken::PercentTprel_Hi:
691 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
692 case AsmToken::PercentTprel_Lo:
693 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
694 }
695 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000696};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000697
698/// MipsOperand - Instances of this class represent a parsed Mips machine
699/// instruction.
700class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000701public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000702 /// Broad categories of register classes
703 /// The exact class is finalized by the render method.
704 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000705 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000706 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000707 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000708 RegKind_FCC = 4, /// FCC
709 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
710 RegKind_MSACtrl = 16, /// MSA control registers
711 RegKind_COP2 = 32, /// COP2
712 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
713 /// context).
714 RegKind_CCR = 128, /// CCR
715 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000716 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000717 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000718 /// Potentially any (e.g. $1)
719 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
720 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000721 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000722 };
723
724private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000725 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000726 k_Immediate, /// An immediate (possibly involving symbol references)
727 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000728 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000729 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000730 k_RegList, /// A physical register list
731 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000732 } Kind;
733
David Blaikie960ea3f2014-06-08 16:18:35 +0000734public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 MipsOperand(KindTy K, MipsAsmParser &Parser)
736 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
737
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000738 ~MipsOperand() override {
739 switch (Kind) {
740 case k_Immediate:
741 break;
742 case k_Memory:
743 delete Mem.Base;
744 break;
745 case k_RegList:
746 delete RegList.List;
747 case k_RegisterIndex:
748 case k_Token:
749 case k_RegPair:
750 break;
751 }
752 }
753
David Blaikie960ea3f2014-06-08 16:18:35 +0000754private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 /// For diagnostics, and checking the assembler temporary
756 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000757
Eric Christopher8996c5d2013-03-15 00:42:55 +0000758 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000759 const char *Data;
760 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000761 };
762
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000763 struct RegIdxOp {
764 unsigned Index; /// Index into the register class
765 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000766 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000768 };
769
770 struct ImmOp {
771 const MCExpr *Val;
772 };
773
774 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000776 const MCExpr *Off;
777 };
778
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000779 struct RegListOp {
780 SmallVector<unsigned, 10> *List;
781 };
782
Jack Carterb4dbc172012-09-05 23:34:03 +0000783 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000784 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000786 struct ImmOp Imm;
787 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000788 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000789 };
790
791 SMLoc StartLoc, EndLoc;
792
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000794 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
795 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000796 const MCRegisterInfo *RegInfo,
797 SMLoc S, SMLoc E,
798 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000799 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 Op->RegIdx.Index = Index;
801 Op->RegIdx.RegInfo = RegInfo;
802 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000803 Op->RegIdx.Tok.Data = Str.data();
804 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 Op->StartLoc = S;
806 Op->EndLoc = E;
807 return Op;
808 }
809
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000810public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 /// Coerce the register to GPR32 and return the real register for the current
812 /// target.
813 unsigned getGPR32Reg() const {
814 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000815 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 unsigned ClassID = Mips::GPR32RegClassID;
817 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000818 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000819
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000820 /// Coerce the register to GPR32 and return the real register for the current
821 /// target.
822 unsigned getGPRMM16Reg() const {
823 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
824 unsigned ClassID = Mips::GPR32RegClassID;
825 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
826 }
827
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 /// Coerce the register to GPR64 and return the real register for the current
829 /// target.
830 unsigned getGPR64Reg() const {
831 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
832 unsigned ClassID = Mips::GPR64RegClassID;
833 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000834 }
835
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836private:
837 /// Coerce the register to AFGR64 and return the real register for the current
838 /// target.
839 unsigned getAFGR64Reg() const {
840 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
841 if (RegIdx.Index % 2 != 0)
842 AsmParser.Warning(StartLoc, "Float register should be even.");
843 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
844 .getRegister(RegIdx.Index / 2);
845 }
846
847 /// Coerce the register to FGR64 and return the real register for the current
848 /// target.
849 unsigned getFGR64Reg() const {
850 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
851 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
852 .getRegister(RegIdx.Index);
853 }
854
855 /// Coerce the register to FGR32 and return the real register for the current
856 /// target.
857 unsigned getFGR32Reg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
859 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
860 .getRegister(RegIdx.Index);
861 }
862
863 /// Coerce the register to FGRH32 and return the real register for the current
864 /// target.
865 unsigned getFGRH32Reg() const {
866 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
867 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
868 .getRegister(RegIdx.Index);
869 }
870
871 /// Coerce the register to FCC and return the real register for the current
872 /// target.
873 unsigned getFCCReg() const {
874 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
875 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
876 .getRegister(RegIdx.Index);
877 }
878
879 /// Coerce the register to MSA128 and return the real register for the current
880 /// target.
881 unsigned getMSA128Reg() const {
882 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
883 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
884 // identical
885 unsigned ClassID = Mips::MSA128BRegClassID;
886 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
887 }
888
889 /// Coerce the register to MSACtrl and return the real register for the
890 /// current target.
891 unsigned getMSACtrlReg() const {
892 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
893 unsigned ClassID = Mips::MSACtrlRegClassID;
894 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
895 }
896
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000897 /// Coerce the register to COP0 and return the real register for the
898 /// current target.
899 unsigned getCOP0Reg() const {
900 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
901 unsigned ClassID = Mips::COP0RegClassID;
902 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
903 }
904
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 /// Coerce the register to COP2 and return the real register for the
906 /// current target.
907 unsigned getCOP2Reg() const {
908 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
909 unsigned ClassID = Mips::COP2RegClassID;
910 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
911 }
912
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000913 /// Coerce the register to COP3 and return the real register for the
914 /// current target.
915 unsigned getCOP3Reg() const {
916 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
917 unsigned ClassID = Mips::COP3RegClassID;
918 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
919 }
920
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 /// Coerce the register to ACC64DSP and return the real register for the
922 /// current target.
923 unsigned getACC64DSPReg() const {
924 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
925 unsigned ClassID = Mips::ACC64DSPRegClassID;
926 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
927 }
928
929 /// Coerce the register to HI32DSP and return the real register for the
930 /// current target.
931 unsigned getHI32DSPReg() const {
932 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
933 unsigned ClassID = Mips::HI32DSPRegClassID;
934 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
935 }
936
937 /// Coerce the register to LO32DSP and return the real register for the
938 /// current target.
939 unsigned getLO32DSPReg() const {
940 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
941 unsigned ClassID = Mips::LO32DSPRegClassID;
942 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
943 }
944
945 /// Coerce the register to CCR and return the real register for the
946 /// current target.
947 unsigned getCCRReg() const {
948 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
949 unsigned ClassID = Mips::CCRRegClassID;
950 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
951 }
952
953 /// Coerce the register to HWRegs and return the real register for the
954 /// current target.
955 unsigned getHWRegsReg() const {
956 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
957 unsigned ClassID = Mips::HWRegsRegClassID;
958 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
959 }
960
961public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000962 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000963 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000964 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000965 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000966 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000967 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000968 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000969 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000970 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000971
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000972 void addRegOperands(MCInst &Inst, unsigned N) const {
973 llvm_unreachable("Use a custom parser instead");
974 }
975
Daniel Sanders21bce302014-04-01 12:35:23 +0000976 /// Render the operand to an MCInst as a GPR32
977 /// Asserts if the wrong number of operands are requested, or the operand
978 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000979 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
980 assert(N == 1 && "Invalid number of operands!");
981 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
982 }
983
984 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
985 assert(N == 1 && "Invalid number of operands!");
986 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
987 }
988
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000989 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
990 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000991 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 }
993
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000994 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
995 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000996 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000997 }
998
Jozef Kolek1904fa22014-11-24 14:25:53 +0000999 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001001 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001002 }
1003
Zoran Jovanovic41688672015-02-10 16:36:20 +00001004 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001006 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001007 }
1008
Daniel Sanders21bce302014-04-01 12:35:23 +00001009 /// Render the operand to an MCInst as a GPR64
1010 /// Asserts if the wrong number of operands are requested, or the operand
1011 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1013 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001014 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001015 }
1016
1017 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1018 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001019 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 }
1021
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001022 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1023 assert(N == 1 && "Invalid number of operands!");
1024 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1025 }
1026
1027 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1028 assert(N == 1 && "Invalid number of operands!");
1029 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1030 }
1031
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1033 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001034 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 }
1036
1037 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1038 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001039 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001040 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001041 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001042 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001043 AsmParser.getParser().printError(
1044 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1045 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001046 }
1047
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001048 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1049 assert(N == 1 && "Invalid number of operands!");
1050 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1051 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1052 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1053 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1054 "registers");
1055 }
1056
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1058 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001059 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 }
1061
1062 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001064 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 }
1066
1067 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001069 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 }
1071
1072 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001074 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 }
1076
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001077 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1080 }
1081
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001082 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001084 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001085 }
1086
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001087 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001089 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001090 }
1091
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001094 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 }
1096
1097 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001100 }
1101
1102 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001104 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 }
1106
1107 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001109 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 }
1111
1112 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001114 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 }
1116
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001117 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001118 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001120 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001121 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001122 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001123 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001124 Inst.addOperand(MCOperand::createImm(Imm));
1125 }
1126
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001127 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001128 void addSImmOperands(MCInst &Inst, unsigned N) const {
1129 if (isImm() && !isConstantImm()) {
1130 addExpr(Inst, getImm());
1131 return;
1132 }
1133 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1134 }
1135
1136 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001137 void addUImmOperands(MCInst &Inst, unsigned N) const {
1138 if (isImm() && !isConstantImm()) {
1139 addExpr(Inst, getImm());
1140 return;
1141 }
1142 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1143 }
1144
Daniel Sanders78e89022016-03-11 11:37:50 +00001145 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1146 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1147 assert(N == 1 && "Invalid number of operands!");
1148 int64_t Imm = getConstantImm() - Offset;
1149 Imm = SignExtend64<Bits>(Imm);
1150 Imm += Offset;
1151 Imm += AdjustOffset;
1152 Inst.addOperand(MCOperand::createImm(Imm));
1153 }
1154
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001155 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001156 assert(N == 1 && "Invalid number of operands!");
1157 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001158 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001159 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001160
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001161 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001162 assert(N == 2 && "Invalid number of operands!");
1163
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001164 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1165 ? getMemBase()->getGPR64Reg()
1166 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001167
1168 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001170 }
1171
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001172 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1173 assert(N == 2 && "Invalid number of operands!");
1174
Jim Grosbache9119e42015-05-13 18:37:00 +00001175 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001176
1177 const MCExpr *Expr = getMemOff();
1178 addExpr(Inst, Expr);
1179 }
1180
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001181 void addRegListOperands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
1183
1184 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001185 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001186 }
1187
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001188 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001190 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001191 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001192 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1193 Inst.addOperand(MCOperand::createReg(
1194 RegIdx.RegInfo->getRegClass(
1195 AsmParser.getABI().AreGprs64bit()
1196 ? Mips::GPR64RegClassID
1197 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1198 Inst.addOperand(MCOperand::createReg(
1199 RegIdx.RegInfo->getRegClass(
1200 AsmParser.getABI().AreGprs64bit()
1201 ? Mips::GPR64RegClassID
1202 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001203 }
1204
Zoran Jovanovic41688672015-02-10 16:36:20 +00001205 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 2 && "Invalid number of operands!");
1207 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001208 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001209 }
1210
Craig Topper56c590a2014-04-29 07:58:02 +00001211 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001212 // As a special case until we sort out the definition of div/divu, accept
1213 // $0/$zero here so that MCK_ZERO works correctly.
1214 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001216
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001217 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001218 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001219
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001220 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001221 int64_t Res;
1222 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001224
Daniel Sanders52da7af2015-11-06 12:11:03 +00001225 bool isConstantImmz() const {
1226 return isConstantImm() && getConstantImm() == 0;
1227 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001228
Daniel Sandersea4f6532015-11-06 12:22:31 +00001229 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1230 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1231 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001232
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001233 template <unsigned Bits> bool isSImm() const {
1234 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001237 template <unsigned Bits> bool isUImm() const {
1238 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1239 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001240
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001241 template <unsigned Bits> bool isAnyImm() const {
1242 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1243 isUInt<Bits>(getConstantImm()))
1244 : isImm();
1245 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001246
Daniel Sanders78e89022016-03-11 11:37:50 +00001247 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1248 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001249 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001250
Hrvoje Varga46458d02016-02-25 12:53:29 +00001251 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1252 return isConstantImm() && getConstantImm() >= Bottom &&
1253 getConstantImm() <= Top;
1254 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001255
Craig Topper56c590a2014-04-29 07:58:02 +00001256 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001257 // Note: It's not possible to pretend that other operand kinds are tokens.
1258 // The matcher emitter checks tokens first.
1259 return Kind == k_Token;
1260 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001261
Craig Topper56c590a2014-04-29 07:58:02 +00001262 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001263
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001264 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001265 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001266 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001267
Simon Dardis4ccda502016-05-27 13:56:36 +00001268 // Allow relocation operators.
1269 // FIXME: This predicate and others need to look through binary expressions
1270 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001271 template <unsigned Bits, unsigned ShiftAmount = 0>
1272 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001273 if (!isMem())
1274 return false;
1275 if (!getMemBase()->isGPRAsmReg())
1276 return false;
1277 if (isa<MCTargetExpr>(getMemOff()) ||
1278 (isConstantMemOff() &&
1279 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1280 return true;
1281 MCValue Res;
1282 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1283 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001284 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001285
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001286 bool isMemWithGRPMM16Base() const {
1287 return isMem() && getMemBase()->isMM16AsmReg();
1288 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001289
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001290 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1291 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1292 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1293 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001294
Jozef Kolek12c69822014-12-23 16:16:33 +00001295 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1296 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1297 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1298 && (getMemBase()->getGPR32Reg() == Mips::SP);
1299 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001300
Daniel Sanderse473dc92016-05-09 13:38:25 +00001301 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1302 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1303 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1304 && (getMemBase()->getGPR32Reg() == Mips::GP);
1305 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001306
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001307 template <unsigned Bits, unsigned ShiftLeftAmount>
1308 bool isScaledUImm() const {
1309 return isConstantImm() &&
1310 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001311 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001312
Daniel Sanders97297772016-03-22 14:40:00 +00001313 template <unsigned Bits, unsigned ShiftLeftAmount>
1314 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001315 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1316 return true;
1317 // Operand can also be a symbol or symbol plus offset in case of relocations.
1318 if (Kind != k_Immediate)
1319 return false;
1320 MCValue Res;
1321 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1322 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001323 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001324
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001325 bool isRegList16() const {
1326 if (!isRegList())
1327 return false;
1328
1329 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001330 if (Size < 2 || Size > 5)
1331 return false;
1332
1333 unsigned R0 = RegList.List->front();
1334 unsigned R1 = RegList.List->back();
1335 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1336 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001337 return false;
1338
1339 int PrevReg = *RegList.List->begin();
1340 for (int i = 1; i < Size - 1; i++) {
1341 int Reg = (*(RegList.List))[i];
1342 if ( Reg != PrevReg + 1)
1343 return false;
1344 PrevReg = Reg;
1345 }
1346
1347 return true;
1348 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001349
Vladimir Medic2b953d02013-10-01 09:48:56 +00001350 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001351
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001352 bool isLSAImm() const {
1353 if (!isConstantImm())
1354 return false;
1355 int64_t Val = getConstantImm();
1356 return 1 <= Val && Val <= 4;
1357 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001358
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001359 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001360
Zoran Jovanovic41688672015-02-10 16:36:20 +00001361 bool isMovePRegPair() const {
1362 if (Kind != k_RegList || RegList.List->size() != 2)
1363 return false;
1364
1365 unsigned R0 = RegList.List->front();
1366 unsigned R1 = RegList.List->back();
1367
1368 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1369 (R0 == Mips::A1 && R1 == Mips::A3) ||
1370 (R0 == Mips::A2 && R1 == Mips::A3) ||
1371 (R0 == Mips::A0 && R1 == Mips::S5) ||
1372 (R0 == Mips::A0 && R1 == Mips::S6) ||
1373 (R0 == Mips::A0 && R1 == Mips::A1) ||
1374 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001375 (R0 == Mips::A0 && R1 == Mips::A3) ||
1376 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1377 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1378 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1379 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1380 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1381 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1382 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1383 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001384 return true;
1385
1386 return false;
1387 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001388
1389 StringRef getToken() const {
1390 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001391 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001392 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001393
Zlatko Buljanba553a62016-05-09 08:07:28 +00001394 bool isRegPair() const {
1395 return Kind == k_RegPair && RegIdx.Index <= 30;
1396 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001397
Craig Topper56c590a2014-04-29 07:58:02 +00001398 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001399 // As a special case until we sort out the definition of div/divu, accept
1400 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001401 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1402 RegIdx.Kind & RegKind_GPR)
1403 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001404
Daniel Sanders976d9382016-07-05 13:38:40 +00001405 llvm_unreachable("Invalid access!");
1406 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001407 }
1408
Jack Carterb4dbc172012-09-05 23:34:03 +00001409 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001410 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001411 return Imm.Val;
1412 }
1413
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001414 int64_t getConstantImm() const {
1415 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001416 int64_t Value = 0;
1417 (void)Val->evaluateAsAbsolute(Value);
1418 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 }
1420
1421 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001422 assert((Kind == k_Memory) && "Invalid access!");
1423 return Mem.Base;
1424 }
1425
1426 const MCExpr *getMemOff() const {
1427 assert((Kind == k_Memory) && "Invalid access!");
1428 return Mem.Off;
1429 }
1430
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001431 int64_t getConstantMemOff() const {
1432 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1433 }
1434
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001435 const SmallVectorImpl<unsigned> &getRegList() const {
1436 assert((Kind == k_RegList) && "Invalid access!");
1437 return *(RegList.List);
1438 }
1439
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001440 unsigned getRegPair() const {
1441 assert((Kind == k_RegPair) && "Invalid access!");
1442 return RegIdx.Index;
1443 }
1444
David Blaikie960ea3f2014-06-08 16:18:35 +00001445 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1446 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001447 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001448 Op->Tok.Data = Str.data();
1449 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001450 Op->StartLoc = S;
1451 Op->EndLoc = S;
1452 return Op;
1453 }
1454
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001455 /// Create a numeric register (e.g. $1). The exact register remains
1456 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001457 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001458 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1459 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001460 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001461 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001462 }
1463
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001464 /// Create a register that is definitely a GPR.
1465 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001466 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001467 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1468 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1469 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001470 }
1471
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001472 /// Create a register that is definitely a FGR.
1473 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001474 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001475 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1476 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1477 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001478 }
1479
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001480 /// Create a register that is definitely a HWReg.
1481 /// This is typically only used for named registers such as $hwr_cpunum.
1482 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001483 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001484 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001485 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001486 }
1487
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001488 /// Create a register that is definitely an FCC.
1489 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001490 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001491 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1492 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1493 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001494 }
1495
1496 /// Create a register that is definitely an ACC.
1497 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001498 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001499 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1500 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1501 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001502 }
1503
1504 /// Create a register that is definitely an MSA128.
1505 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001506 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001507 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1508 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1509 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001510 }
1511
1512 /// Create a register that is definitely an MSACtrl.
1513 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001514 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001515 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1516 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1517 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001518 }
1519
David Blaikie960ea3f2014-06-08 16:18:35 +00001520 static std::unique_ptr<MipsOperand>
1521 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001522 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001523 Op->Imm.Val = Val;
1524 Op->StartLoc = S;
1525 Op->EndLoc = E;
1526 return Op;
1527 }
1528
David Blaikie960ea3f2014-06-08 16:18:35 +00001529 static std::unique_ptr<MipsOperand>
1530 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1531 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001532 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001533 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001534 Op->Mem.Off = Off;
1535 Op->StartLoc = S;
1536 Op->EndLoc = E;
1537 return Op;
1538 }
1539
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001540 static std::unique_ptr<MipsOperand>
1541 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1542 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001543 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001544
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001545 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001546 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001547 Op->StartLoc = StartLoc;
1548 Op->EndLoc = EndLoc;
1549 return Op;
1550 }
1551
Daniel Sandersd044e492016-05-09 13:10:57 +00001552 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1553 SMLoc S, SMLoc E,
1554 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001555 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001556 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001557 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1558 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001559 Op->StartLoc = S;
1560 Op->EndLoc = E;
1561 return Op;
1562 }
1563
Simon Dardis509da1a2017-02-13 16:06:48 +00001564 bool isGPRZeroAsmReg() const {
1565 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1566 }
1567
1568 bool isGPRNonZeroAsmReg() const {
1569 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1570 RegIdx.Index <= 31;
1571 }
1572
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001573 bool isGPRAsmReg() const {
1574 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001575 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001576
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001577 bool isMM16AsmReg() const {
1578 if (!(isRegIdx() && RegIdx.Kind))
1579 return false;
1580 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1581 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001582
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001583 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001584 bool isMM16AsmRegZero() const {
1585 if (!(isRegIdx() && RegIdx.Kind))
1586 return false;
1587 return (RegIdx.Index == 0 ||
1588 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1589 RegIdx.Index == 17);
1590 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001591
Zoran Jovanovic41688672015-02-10 16:36:20 +00001592 bool isMM16AsmRegMoveP() const {
1593 if (!(isRegIdx() && RegIdx.Kind))
1594 return false;
1595 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1596 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1597 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001598
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001599 bool isFGRAsmReg() const {
1600 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1601 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001602 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001603
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001604 bool isStrictlyFGRAsmReg() const {
1605 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1606 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1607 }
1608
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001609 bool isHWRegsAsmReg() const {
1610 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001611 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001613 bool isCCRAsmReg() const {
1614 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001615 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001616
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001617 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001618 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1619 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001620 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001621 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001622
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001623 bool isACCAsmReg() const {
1624 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001625 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001626
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001627 bool isCOP0AsmReg() const {
1628 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1629 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001630
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 bool isCOP2AsmReg() const {
1632 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001633 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001634
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001635 bool isCOP3AsmReg() const {
1636 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1637 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001638
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001639 bool isMSA128AsmReg() const {
1640 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 bool isMSACtrlAsmReg() const {
1644 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001645 }
1646
Jack Carterb4dbc172012-09-05 23:34:03 +00001647 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001648 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001649 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001650 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001651
Craig Topper56c590a2014-04-29 07:58:02 +00001652 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 switch (Kind) {
1654 case k_Immediate:
1655 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001656 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001657 OS << ">";
1658 break;
1659 case k_Memory:
1660 OS << "Mem<";
1661 Mem.Base->print(OS);
1662 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001663 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001664 OS << ">";
1665 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001666 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001667 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1668 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001669 break;
1670 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001671 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001673 case k_RegList:
1674 OS << "RegList< ";
1675 for (auto Reg : (*RegList.List))
1676 OS << Reg << " ";
1677 OS << ">";
1678 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001679 case k_RegPair:
1680 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1681 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001682 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001683 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001684
1685 bool isValidForTie(const MipsOperand &Other) const {
1686 if (Kind != Other.Kind)
1687 return false;
1688
1689 switch (Kind) {
1690 default:
1691 llvm_unreachable("Unexpected kind");
1692 return false;
1693 case k_RegisterIndex: {
1694 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1695 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1696 return Token == OtherToken;
1697 }
1698 }
1699 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001700}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001701
1702} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001703
Jack Carter9e65aa32013-03-22 00:05:30 +00001704namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001705
Jack Carter9e65aa32013-03-22 00:05:30 +00001706extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001707
1708} // end namespace llvm
1709
Jack Carter9e65aa32013-03-22 00:05:30 +00001710static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1711 return MipsInsts[Opcode];
1712}
1713
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001714static bool hasShortDelaySlot(unsigned Opcode) {
1715 switch (Opcode) {
1716 case Mips::JALS_MM:
1717 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001718 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001719 case Mips::BGEZALS_MM:
1720 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001721 return true;
1722 default:
1723 return false;
1724 }
1725}
1726
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001727static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1728 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1729 return &SRExpr->getSymbol();
1730 }
1731
1732 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1733 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1734 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1735
1736 if (LHSSym)
1737 return LHSSym;
1738
1739 if (RHSSym)
1740 return RHSSym;
1741
1742 return nullptr;
1743 }
1744
1745 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1746 return getSingleMCSymbol(UExpr->getSubExpr());
1747
1748 return nullptr;
1749}
1750
1751static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1752 if (isa<MCSymbolRefExpr>(Expr))
1753 return 1;
1754
1755 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1756 return countMCSymbolRefExpr(BExpr->getLHS()) +
1757 countMCSymbolRefExpr(BExpr->getRHS());
1758
1759 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1760 return countMCSymbolRefExpr(UExpr->getSubExpr());
1761
1762 return 0;
1763}
1764
Jack Carter9e65aa32013-03-22 00:05:30 +00001765bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001766 MCStreamer &Out,
1767 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001768 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001769 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001770 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001771
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001773
1774 if (MCID.isBranch() || MCID.isCall()) {
1775 const unsigned Opcode = Inst.getOpcode();
1776 MCOperand Offset;
1777
1778 switch (Opcode) {
1779 default:
1780 break;
Kai Nackee0245392015-01-27 19:11:28 +00001781 case Mips::BBIT0:
1782 case Mips::BBIT032:
1783 case Mips::BBIT1:
1784 case Mips::BBIT132:
1785 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001786 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001787
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001788 case Mips::BEQ:
1789 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001790 case Mips::BEQ_MM:
1791 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001792 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001793 Offset = Inst.getOperand(2);
1794 if (!Offset.isImm())
1795 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001796 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001797 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001798 if (OffsetToAlignment(Offset.getImm(),
1799 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001800 return Error(IDLoc, "branch to misaligned address");
1801 break;
1802 case Mips::BGEZ:
1803 case Mips::BGTZ:
1804 case Mips::BLEZ:
1805 case Mips::BLTZ:
1806 case Mips::BGEZAL:
1807 case Mips::BLTZAL:
1808 case Mips::BC1F:
1809 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001810 case Mips::BGEZ_MM:
1811 case Mips::BGTZ_MM:
1812 case Mips::BLEZ_MM:
1813 case Mips::BLTZ_MM:
1814 case Mips::BGEZAL_MM:
1815 case Mips::BLTZAL_MM:
1816 case Mips::BC1F_MM:
1817 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001818 case Mips::BC1EQZC_MMR6:
1819 case Mips::BC1NEZC_MMR6:
1820 case Mips::BC2EQZC_MMR6:
1821 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001822 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001823 Offset = Inst.getOperand(1);
1824 if (!Offset.isImm())
1825 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001826 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001827 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001828 if (OffsetToAlignment(Offset.getImm(),
1829 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001830 return Error(IDLoc, "branch to misaligned address");
1831 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001832 case Mips::BGEC: case Mips::BGEC_MMR6:
1833 case Mips::BLTC: case Mips::BLTC_MMR6:
1834 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1835 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1836 case Mips::BEQC: case Mips::BEQC_MMR6:
1837 case Mips::BNEC: case Mips::BNEC_MMR6:
1838 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1839 Offset = Inst.getOperand(2);
1840 if (!Offset.isImm())
1841 break; // We'll deal with this situation later on when applying fixups.
1842 if (!isIntN(18, Offset.getImm()))
1843 return Error(IDLoc, "branch target out of range");
1844 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1845 return Error(IDLoc, "branch to misaligned address");
1846 break;
1847 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1848 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1849 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1850 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1851 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1852 Offset = Inst.getOperand(1);
1853 if (!Offset.isImm())
1854 break; // We'll deal with this situation later on when applying fixups.
1855 if (!isIntN(18, Offset.getImm()))
1856 return Error(IDLoc, "branch target out of range");
1857 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1858 return Error(IDLoc, "branch to misaligned address");
1859 break;
1860 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1861 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1862 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1863 Offset = Inst.getOperand(1);
1864 if (!Offset.isImm())
1865 break; // We'll deal with this situation later on when applying fixups.
1866 if (!isIntN(23, Offset.getImm()))
1867 return Error(IDLoc, "branch target out of range");
1868 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1869 return Error(IDLoc, "branch to misaligned address");
1870 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001871 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001872 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001873 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001874 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001875 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1876 Offset = Inst.getOperand(1);
1877 if (!Offset.isImm())
1878 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001879 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001880 return Error(IDLoc, "branch target out of range");
1881 if (OffsetToAlignment(Offset.getImm(), 2LL))
1882 return Error(IDLoc, "branch to misaligned address");
1883 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001884 }
1885 }
1886
Daniel Sandersa84989a2014-06-16 13:25:35 +00001887 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1888 // We still accept it but it is a normal nop.
1889 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1890 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1891 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1892 "nop instruction");
1893 }
1894
Kai Nackee0245392015-01-27 19:11:28 +00001895 if (hasCnMips()) {
1896 const unsigned Opcode = Inst.getOpcode();
1897 MCOperand Opnd;
1898 int Imm;
1899
1900 switch (Opcode) {
1901 default:
1902 break;
1903
1904 case Mips::BBIT0:
1905 case Mips::BBIT032:
1906 case Mips::BBIT1:
1907 case Mips::BBIT132:
1908 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1909 // The offset is handled above
1910 Opnd = Inst.getOperand(1);
1911 if (!Opnd.isImm())
1912 return Error(IDLoc, "expected immediate operand kind");
1913 Imm = Opnd.getImm();
1914 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1915 Opcode == Mips::BBIT1 ? 63 : 31))
1916 return Error(IDLoc, "immediate operand value out of range");
1917 if (Imm > 31) {
1918 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1919 : Mips::BBIT132);
1920 Inst.getOperand(1).setImm(Imm - 32);
1921 }
1922 break;
1923
Kai Nackee0245392015-01-27 19:11:28 +00001924 case Mips::SEQi:
1925 case Mips::SNEi:
1926 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1927 Opnd = Inst.getOperand(2);
1928 if (!Opnd.isImm())
1929 return Error(IDLoc, "expected immediate operand kind");
1930 Imm = Opnd.getImm();
1931 if (!isInt<10>(Imm))
1932 return Error(IDLoc, "immediate operand value out of range");
1933 break;
1934 }
1935 }
1936
Simon Dardis509da1a2017-02-13 16:06:48 +00001937 // Warn on division by zero. We're checking here as all instructions get
1938 // processed here, not just the macros that need expansion.
1939 //
1940 // The MIPS backend models most of the divison instructions and macros as
1941 // three operand instructions. The pre-R6 divide instructions however have
1942 // two operands and explicitly define HI/LO as part of the instruction,
1943 // not in the operands.
1944 unsigned FirstOp = 1;
1945 unsigned SecondOp = 2;
1946 switch (Inst.getOpcode()) {
1947 default:
1948 break;
1949 case Mips::SDivIMacro:
1950 case Mips::UDivIMacro:
1951 case Mips::DSDivIMacro:
1952 case Mips::DUDivIMacro:
1953 if (Inst.getOperand(2).getImm() == 0) {
1954 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1955 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1956 Warning(IDLoc, "dividing zero by zero");
1957 else
1958 Warning(IDLoc, "division by zero");
1959 }
1960 break;
1961 case Mips::DSDIV:
1962 case Mips::SDIV:
1963 case Mips::UDIV:
1964 case Mips::DUDIV:
1965 case Mips::UDIV_MM:
1966 case Mips::SDIV_MM:
1967 FirstOp = 0;
1968 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001969 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001970 case Mips::SDivMacro:
1971 case Mips::DSDivMacro:
1972 case Mips::UDivMacro:
1973 case Mips::DUDivMacro:
1974 case Mips::DIV:
1975 case Mips::DIVU:
1976 case Mips::DDIV:
1977 case Mips::DDIVU:
1978 case Mips::DIVU_MMR6:
1979 case Mips::DDIVU_MM64R6:
1980 case Mips::DIV_MMR6:
1981 case Mips::DDIV_MM64R6:
1982 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
1983 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
1984 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
1985 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
1986 Warning(IDLoc, "dividing zero by zero");
1987 else
1988 Warning(IDLoc, "division by zero");
1989 }
1990 break;
1991 }
1992
Simon Atanasyan50485142016-12-12 17:40:26 +00001993 // For PIC code convert unconditional jump to unconditional branch.
1994 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1995 inPicMode()) {
1996 MCInst BInst;
1997 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1998 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1999 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2000 BInst.addOperand(Inst.getOperand(0));
2001 Inst = BInst;
2002 }
2003
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002004 // This expansion is not in a function called by tryExpandInstruction()
2005 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002006 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2007 inPicMode()) {
2008 warnIfNoMacro(IDLoc);
2009
2010 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2011
2012 // We can do this expansion if there's only 1 symbol in the argument
2013 // expression.
2014 if (countMCSymbolRefExpr(JalExpr) > 1)
2015 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2016
2017 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002018 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002019 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2020
2021 // FIXME: Add support for label+offset operands (currently causes an error).
2022 // FIXME: Add support for forward-declared local symbols.
2023 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002024 if (JalSym->isInSection() || JalSym->isTemporary() ||
2025 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002026 if (isABI_O32()) {
2027 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002028 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002029 // R_(MICRO)MIPS_GOT16 label
2030 // addiu $25, $25, 0
2031 // R_(MICRO)MIPS_LO16 label
2032 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002033 const MCExpr *Got16RelocExpr =
2034 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2035 const MCExpr *Lo16RelocExpr =
2036 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002037
Daniel Sandersa736b372016-04-29 13:33:12 +00002038 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2039 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2040 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2041 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002042 } else if (isABI_N32() || isABI_N64()) {
2043 // If it's a local symbol and the N32/N64 ABIs are being used,
2044 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002045 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002046 // R_(MICRO)MIPS_GOT_DISP label
2047 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002048 const MCExpr *GotDispRelocExpr =
2049 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002050
Daniel Sandersa736b372016-04-29 13:33:12 +00002051 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2052 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2053 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002054 }
2055 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002056 // If it's an external/weak symbol, we expand to:
2057 // lw/ld $25, 0($gp)
2058 // R_(MICRO)MIPS_CALL16 label
2059 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002060 const MCExpr *Call16RelocExpr =
2061 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002062
Daniel Sandersa736b372016-04-29 13:33:12 +00002063 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2064 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002065 }
2066
2067 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002068 if (IsCpRestoreSet && inMicroMipsMode())
2069 JalrInst.setOpcode(Mips::JALRS_MM);
2070 else
2071 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002072 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2073 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2074
2075 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2076 // This relocation is supposed to be an optimization hint for the linker
2077 // and is not necessary for correctness.
2078
2079 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002080 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002081 }
2082
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002083 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2084 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002085 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002086 // reference or immediate we may have to expand instructions.
2087 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002088 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002089 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2090 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002091 MCOperand &Op = Inst.getOperand(i);
2092 if (Op.isImm()) {
2093 int MemOffset = Op.getImm();
2094 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002095 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002096 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002097 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002098 }
2099 } else if (Op.isExpr()) {
2100 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002102 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002103 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002104 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002105 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002106 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002107 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002108 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002109 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002110 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002111 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002112 }
2113 }
2114 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002115 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002116 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002117
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002118 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002119 if (MCID.mayLoad()) {
2120 // Try to create 16-bit GP relative load instruction.
2121 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2122 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2123 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2124 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2125 MCOperand &Op = Inst.getOperand(i);
2126 if (Op.isImm()) {
2127 int MemOffset = Op.getImm();
2128 MCOperand &DstReg = Inst.getOperand(0);
2129 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002130 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002131 getContext().getRegisterInfo()->getRegClass(
2132 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002133 (BaseReg.getReg() == Mips::GP ||
2134 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002135
Daniel Sandersa736b372016-04-29 13:33:12 +00002136 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2137 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002138 return false;
2139 }
2140 }
2141 }
2142 } // for
2143 } // if load
2144
2145 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2146
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002147 MCOperand Opnd;
2148 int Imm;
2149
2150 switch (Inst.getOpcode()) {
2151 default:
2152 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002153 case Mips::ADDIUSP_MM:
2154 Opnd = Inst.getOperand(0);
2155 if (!Opnd.isImm())
2156 return Error(IDLoc, "expected immediate operand kind");
2157 Imm = Opnd.getImm();
2158 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2159 Imm % 4 != 0)
2160 return Error(IDLoc, "immediate operand value out of range");
2161 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002162 case Mips::SLL16_MM:
2163 case Mips::SRL16_MM:
2164 Opnd = Inst.getOperand(2);
2165 if (!Opnd.isImm())
2166 return Error(IDLoc, "expected immediate operand kind");
2167 Imm = Opnd.getImm();
2168 if (Imm < 1 || Imm > 8)
2169 return Error(IDLoc, "immediate operand value out of range");
2170 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002171 case Mips::LI16_MM:
2172 Opnd = Inst.getOperand(1);
2173 if (!Opnd.isImm())
2174 return Error(IDLoc, "expected immediate operand kind");
2175 Imm = Opnd.getImm();
2176 if (Imm < -1 || Imm > 126)
2177 return Error(IDLoc, "immediate operand value out of range");
2178 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002179 case Mips::ADDIUR2_MM:
2180 Opnd = Inst.getOperand(2);
2181 if (!Opnd.isImm())
2182 return Error(IDLoc, "expected immediate operand kind");
2183 Imm = Opnd.getImm();
2184 if (!(Imm == 1 || Imm == -1 ||
2185 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2186 return Error(IDLoc, "immediate operand value out of range");
2187 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002188 case Mips::ANDI16_MM:
2189 Opnd = Inst.getOperand(2);
2190 if (!Opnd.isImm())
2191 return Error(IDLoc, "expected immediate operand kind");
2192 Imm = Opnd.getImm();
2193 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2194 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2195 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2196 return Error(IDLoc, "immediate operand value out of range");
2197 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002198 case Mips::LBU16_MM:
2199 Opnd = Inst.getOperand(2);
2200 if (!Opnd.isImm())
2201 return Error(IDLoc, "expected immediate operand kind");
2202 Imm = Opnd.getImm();
2203 if (Imm < -1 || Imm > 14)
2204 return Error(IDLoc, "immediate operand value out of range");
2205 break;
2206 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002207 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002208 Opnd = Inst.getOperand(2);
2209 if (!Opnd.isImm())
2210 return Error(IDLoc, "expected immediate operand kind");
2211 Imm = Opnd.getImm();
2212 if (Imm < 0 || Imm > 15)
2213 return Error(IDLoc, "immediate operand value out of range");
2214 break;
2215 case Mips::LHU16_MM:
2216 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002217 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002218 Opnd = Inst.getOperand(2);
2219 if (!Opnd.isImm())
2220 return Error(IDLoc, "expected immediate operand kind");
2221 Imm = Opnd.getImm();
2222 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2223 return Error(IDLoc, "immediate operand value out of range");
2224 break;
2225 case Mips::LW16_MM:
2226 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002227 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002228 Opnd = Inst.getOperand(2);
2229 if (!Opnd.isImm())
2230 return Error(IDLoc, "expected immediate operand kind");
2231 Imm = Opnd.getImm();
2232 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2233 return Error(IDLoc, "immediate operand value out of range");
2234 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002235 case Mips::ADDIUPC_MM:
2236 MCOperand Opnd = Inst.getOperand(1);
2237 if (!Opnd.isImm())
2238 return Error(IDLoc, "expected immediate operand kind");
2239 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002240 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002241 return Error(IDLoc, "immediate operand value out of range");
2242 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002243 }
2244 }
2245
Daniel Sandersd8c07762016-04-18 12:35:36 +00002246 bool FillDelaySlot =
2247 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2248 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002249 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002250
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002251 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002252 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002253 switch (ExpandResult) {
2254 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002255 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002256 break;
2257 case MER_Success:
2258 break;
2259 case MER_Fail:
2260 return true;
2261 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002262
Daniel Sanderscda908a2016-05-16 09:10:13 +00002263 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2264 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2265 if (inMicroMipsMode())
2266 TOut.setUsesMicroMips();
2267
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002268 // If this instruction has a delay slot and .set reorder is active,
2269 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002270 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002271 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2272 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002273 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002274
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002275 if ((Inst.getOpcode() == Mips::JalOneReg ||
2276 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2277 isPicAndNotNxxAbi()) {
2278 if (IsCpRestoreSet) {
2279 // We need a NOP between the JALR and the LW:
2280 // If .set reorder has been used, we've already emitted a NOP.
2281 // If .set noreorder has been used, we need to emit a NOP at this point.
2282 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002283 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2284 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002285
2286 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002287 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002288 } else
2289 Warning(IDLoc, "no .cprestore used in PIC mode");
2290 }
2291
Jack Carter9e65aa32013-03-22 00:05:30 +00002292 return false;
2293}
2294
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002295MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002296MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2297 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002298 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002299 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002300 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002301 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002302 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002303 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002304 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002305 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002306 case Mips::LoadAddrImm64:
2307 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2308 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2309 "expected immediate operand kind");
2310
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002311 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2312 Inst.getOperand(1),
2313 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002314 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002315 ? MER_Fail
2316 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002317 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002318 case Mips::LoadAddrReg64:
2319 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2320 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2321 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2322 "expected immediate operand kind");
2323
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002324 return expandLoadAddress(Inst.getOperand(0).getReg(),
2325 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2326 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002327 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002328 ? MER_Fail
2329 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002330 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002331 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002332 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2333 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002334 case Mips::SWM_MM:
2335 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002336 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2337 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002338 case Mips::JalOneReg:
2339 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002340 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002341 case Mips::BneImm:
2342 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002343 case Mips::BEQLImmMacro:
2344 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002345 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002346 case Mips::BLT:
2347 case Mips::BLE:
2348 case Mips::BGE:
2349 case Mips::BGT:
2350 case Mips::BLTU:
2351 case Mips::BLEU:
2352 case Mips::BGEU:
2353 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002354 case Mips::BLTL:
2355 case Mips::BLEL:
2356 case Mips::BGEL:
2357 case Mips::BGTL:
2358 case Mips::BLTUL:
2359 case Mips::BLEUL:
2360 case Mips::BGEUL:
2361 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002362 case Mips::BLTImmMacro:
2363 case Mips::BLEImmMacro:
2364 case Mips::BGEImmMacro:
2365 case Mips::BGTImmMacro:
2366 case Mips::BLTUImmMacro:
2367 case Mips::BLEUImmMacro:
2368 case Mips::BGEUImmMacro:
2369 case Mips::BGTUImmMacro:
2370 case Mips::BLTLImmMacro:
2371 case Mips::BLELImmMacro:
2372 case Mips::BGELImmMacro:
2373 case Mips::BGTLImmMacro:
2374 case Mips::BLTULImmMacro:
2375 case Mips::BLEULImmMacro:
2376 case Mips::BGEULImmMacro:
2377 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002378 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002379 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002380 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002381 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2382 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002383 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002384 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002385 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2386 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002387 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002388 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002389 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2390 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002391 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002392 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002393 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2394 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002395 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002396 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2397 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002398 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002399 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002400 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002401 case Mips::PseudoTRUNC_W_D:
2402 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2403 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002404
2405 case Mips::LoadImmSingleGPR:
2406 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2407 ? MER_Fail
2408 : MER_Success;
2409 case Mips::LoadImmSingleFGR:
2410 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2411 ? MER_Fail
2412 : MER_Success;
2413 case Mips::LoadImmDoubleGPR:
2414 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2415 ? MER_Fail
2416 : MER_Success;
2417 case Mips::LoadImmDoubleFGR:
2418 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2419 ? MER_Fail
2420 : MER_Success;
2421 case Mips::LoadImmDoubleFGR_32:
2422 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2423 ? MER_Fail
2424 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002425 case Mips::Ulh:
2426 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2427 case Mips::Ulhu:
2428 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002429 case Mips::Ush:
2430 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002431 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002432 case Mips::Usw:
2433 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002434 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002435 case Mips::NORImm64:
2436 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2437 case Mips::SLTImm64:
2438 if (isInt<16>(Inst.getOperand(2).getImm())) {
2439 Inst.setOpcode(Mips::SLTi64);
2440 return MER_NotAMacro;
2441 }
2442 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2443 case Mips::SLTUImm64:
2444 if (isInt<16>(Inst.getOperand(2).getImm())) {
2445 Inst.setOpcode(Mips::SLTiu64);
2446 return MER_NotAMacro;
2447 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002448 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002449 case Mips::ADDi: case Mips::ADDi_MM:
2450 case Mips::ADDiu: case Mips::ADDiu_MM:
2451 case Mips::SLTi: case Mips::SLTi_MM:
2452 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002453 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2454 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2455 int64_t ImmValue = Inst.getOperand(2).getImm();
2456 if (isInt<16>(ImmValue))
2457 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002458 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2459 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002460 }
2461 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002462 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2463 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2464 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002465 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2466 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2467 int64_t ImmValue = Inst.getOperand(2).getImm();
2468 if (isUInt<16>(ImmValue))
2469 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002470 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2471 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002472 }
2473 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002474 case Mips::ROL:
2475 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002476 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002477 case Mips::ROLImm:
2478 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002479 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002480 case Mips::DROL:
2481 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002482 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002483 case Mips::DROLImm:
2484 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002485 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002486 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002487 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002488 case Mips::MULImmMacro:
2489 case Mips::DMULImmMacro:
2490 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2491 case Mips::MULOMacro:
2492 case Mips::DMULOMacro:
2493 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2494 case Mips::MULOUMacro:
2495 case Mips::DMULOUMacro:
2496 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2497 case Mips::DMULMacro:
2498 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002499 case Mips::LDMacro:
2500 case Mips::SDMacro:
2501 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2502 Inst.getOpcode() == Mips::LDMacro)
2503 ? MER_Fail
2504 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002505 case Mips::SEQMacro:
2506 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2507 case Mips::SEQIMacro:
2508 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002509 }
Jack Carter30a59822012-10-04 04:03:53 +00002510}
Jack Carter92995f12012-10-06 00:53:28 +00002511
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002512bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002513 MCStreamer &Out,
2514 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002515 MipsTargetStreamer &TOut = getTargetStreamer();
2516
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002517 // Create a JALR instruction which is going to replace the pseudo-JAL.
2518 MCInst JalrInst;
2519 JalrInst.setLoc(IDLoc);
2520 const MCOperand FirstRegOp = Inst.getOperand(0);
2521 const unsigned Opcode = Inst.getOpcode();
2522
2523 if (Opcode == Mips::JalOneReg) {
2524 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002525 if (IsCpRestoreSet && inMicroMipsMode()) {
2526 JalrInst.setOpcode(Mips::JALRS16_MM);
2527 JalrInst.addOperand(FirstRegOp);
2528 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002529 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002530 JalrInst.addOperand(FirstRegOp);
2531 } else {
2532 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002533 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002534 JalrInst.addOperand(FirstRegOp);
2535 }
2536 } else if (Opcode == Mips::JalTwoReg) {
2537 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002538 if (IsCpRestoreSet && inMicroMipsMode())
2539 JalrInst.setOpcode(Mips::JALRS_MM);
2540 else
2541 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002542 JalrInst.addOperand(FirstRegOp);
2543 const MCOperand SecondRegOp = Inst.getOperand(1);
2544 JalrInst.addOperand(SecondRegOp);
2545 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002546 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002547
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002548 // If .set reorder is active and branch instruction has a delay slot,
2549 // emit a NOP after it.
2550 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002551 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2552 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2553 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002554
2555 return false;
2556}
2557
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002558/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002559template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002560 unsigned BitNum = findFirstSet(x);
2561
2562 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2563}
2564
2565/// Load (or add) an immediate into a register.
2566///
2567/// @param ImmValue The immediate to load.
2568/// @param DstReg The register that will hold the immediate.
2569/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2570/// for a simple initialization.
2571/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2572/// @param IsAddress True if the immediate represents an address. False if it
2573/// is an integer.
2574/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002575bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002576 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002577 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2578 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002579 MipsTargetStreamer &TOut = getTargetStreamer();
2580
Toma Tabacu00e98672015-05-01 12:19:27 +00002581 if (!Is32BitImm && !isGP64bit()) {
2582 Error(IDLoc, "instruction requires a 64-bit architecture");
2583 return true;
2584 }
2585
Daniel Sanders03f9c012015-07-14 12:24:22 +00002586 if (Is32BitImm) {
2587 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2588 // Sign extend up to 64-bit so that the predicates match the hardware
2589 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2590 // true.
2591 ImmValue = SignExtend64<32>(ImmValue);
2592 } else {
2593 Error(IDLoc, "instruction requires a 32-bit immediate");
2594 return true;
2595 }
2596 }
2597
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002598 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2599 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2600
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002601 bool UseSrcReg = false;
2602 if (SrcReg != Mips::NoRegister)
2603 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002604
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002605 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002606 if (UseSrcReg &&
2607 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002608 // At this point we need AT to perform the expansions and we exit if it is
2609 // not available.
2610 unsigned ATReg = getATReg(IDLoc);
2611 if (!ATReg)
2612 return true;
2613 TmpReg = ATReg;
2614 }
2615
Daniel Sanders03f9c012015-07-14 12:24:22 +00002616 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002617 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002618 SrcReg = ZeroReg;
2619
2620 // This doesn't quite follow the usual ABI expectations for N32 but matches
2621 // traditional assembler behaviour. N32 would normally use addiu for both
2622 // integers and addresses.
2623 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002624 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002625 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002626 }
2627
Daniel Sandersa736b372016-04-29 13:33:12 +00002628 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002629 return false;
2630 }
2631
2632 if (isUInt<16>(ImmValue)) {
2633 unsigned TmpReg = DstReg;
2634 if (SrcReg == DstReg) {
2635 TmpReg = getATReg(IDLoc);
2636 if (!TmpReg)
2637 return true;
2638 }
2639
Daniel Sandersa736b372016-04-29 13:33:12 +00002640 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002641 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002642 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002643 return false;
2644 }
2645
2646 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002647 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002648
Toma Tabacu79588102015-04-29 10:19:56 +00002649 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2650 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002651 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002652 // Traditional behaviour seems to special case this particular value. It's
2653 // not clear why other masks are handled differently.
2654 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002655 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2656 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002657 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002658 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002659 return false;
2660 }
2661
2662 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002663 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002664 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2665 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002666 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002667 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002668 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002669 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002670 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002671 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002672
Daniel Sandersa736b372016-04-29 13:33:12 +00002673 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002674 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002675 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002676 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002677 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002678 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002679 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002680
2681 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2682 if (Is32BitImm) {
2683 Error(IDLoc, "instruction requires a 32-bit immediate");
2684 return true;
2685 }
2686
2687 // Traditionally, these immediates are shifted as little as possible and as
2688 // such we align the most significant bit to bit 15 of our temporary.
2689 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2690 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2691 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2692 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002693 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2694 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002695
2696 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002697 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002698
2699 return false;
2700 }
2701
2702 warnIfNoMacro(IDLoc);
2703
2704 // The remaining case is packed with a sequence of dsll and ori with zeros
2705 // being omitted and any neighbouring dsll's being coalesced.
2706 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2707
2708 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2709 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002710 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002711 return false;
2712
2713 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2714 // skip it and defer the shift to the next chunk.
2715 unsigned ShiftCarriedForwards = 16;
2716 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2717 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2718
2719 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002720 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2721 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002722 ShiftCarriedForwards = 0;
2723 }
2724
2725 ShiftCarriedForwards += 16;
2726 }
2727 ShiftCarriedForwards -= 16;
2728
2729 // Finish any remaining shifts left by trailing zeros.
2730 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002731 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002732
2733 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002734 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002735
Matheus Almeida3813d572014-06-19 14:39:14 +00002736 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002737}
Jack Carter92995f12012-10-06 00:53:28 +00002738
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002739bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002740 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002741 const MCOperand &ImmOp = Inst.getOperand(1);
2742 assert(ImmOp.isImm() && "expected immediate operand kind");
2743 const MCOperand &DstRegOp = Inst.getOperand(0);
2744 assert(DstRegOp.isReg() && "expected register operand kind");
2745
2746 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002747 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002748 return true;
2749
2750 return false;
2751}
2752
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002753bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2754 const MCOperand &Offset,
2755 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002756 MCStreamer &Out,
2757 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002758 // la can't produce a usable address when addresses are 64-bit.
2759 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2760 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2761 // We currently can't do this because we depend on the equality
2762 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2763 Error(IDLoc, "la used to load 64-bit address");
2764 // Continue as if we had 'dla' instead.
2765 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002766 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002767 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002768
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002769 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002770 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002771 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002772 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002773 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002774
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002775 if (!Offset.isImm())
2776 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002777 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002778
Scott Egerton24557012016-01-21 15:11:01 +00002779 if (!ABI.ArePtrs64bit()) {
2780 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2781 Is32BitAddress = true;
2782 }
2783
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002784 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002785 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002786}
2787
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002788bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2789 unsigned DstReg, unsigned SrcReg,
2790 bool Is32BitSym, SMLoc IDLoc,
2791 MCStreamer &Out,
2792 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002793 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002794 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002795 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002796 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002797
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002798 if (inPicMode() && ABI.IsO32()) {
2799 MCValue Res;
2800 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2801 Error(IDLoc, "expected relocatable expression");
2802 return true;
2803 }
2804 if (Res.getSymB() != nullptr) {
2805 Error(IDLoc, "expected relocatable expression with only one symbol");
2806 return true;
2807 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002808
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002809 // The case where the result register is $25 is somewhat special. If the
2810 // symbol in the final relocation is external and not modified with a
2811 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2812 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002813 Res.getConstant() == 0 &&
2814 !(Res.getSymA()->getSymbol().isInSection() ||
2815 Res.getSymA()->getSymbol().isTemporary() ||
2816 (Res.getSymA()->getSymbol().isELF() &&
2817 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2818 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002819 const MCExpr *CallExpr =
2820 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2821 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2822 MCOperand::createExpr(CallExpr), IDLoc, STI);
2823 return false;
2824 }
2825
2826 // The remaining cases are:
2827 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2828 // >addiu $tmp, $tmp, %lo(offset)
2829 // >addiu $rd, $tmp, $rs
2830 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2831 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2832 // >addiu $rd, $tmp, $rs
2833 // The addiu's marked with a '>' may be omitted if they are redundant. If
2834 // this happens then the last instruction must use $rd as the result
2835 // register.
2836 const MipsMCExpr *GotExpr =
2837 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2838 const MCExpr *LoExpr = nullptr;
2839 if (Res.getSymA()->getSymbol().isInSection() ||
2840 Res.getSymA()->getSymbol().isTemporary())
2841 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2842 else if (Res.getConstant() != 0) {
2843 // External symbols fully resolve the symbol with just the %got(symbol)
2844 // but we must still account for any offset to the symbol for expressions
2845 // like symbol+8.
2846 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2847 }
2848
2849 unsigned TmpReg = DstReg;
2850 if (UseSrcReg &&
2851 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2852 SrcReg)) {
2853 // If $rs is the same as $rd, we need to use AT.
2854 // If it is not available we exit.
2855 unsigned ATReg = getATReg(IDLoc);
2856 if (!ATReg)
2857 return true;
2858 TmpReg = ATReg;
2859 }
2860
2861 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2862 MCOperand::createExpr(GotExpr), IDLoc, STI);
2863
2864 if (LoExpr)
2865 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2866 IDLoc, STI);
2867
2868 if (UseSrcReg)
2869 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2870
2871 return false;
2872 }
2873
Simon Dardisda96c432017-06-30 15:44:27 +00002874 if (inPicMode() && ABI.ArePtrs64bit()) {
2875 MCValue Res;
2876 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2877 Error(IDLoc, "expected relocatable expression");
2878 return true;
2879 }
2880 if (Res.getSymB() != nullptr) {
2881 Error(IDLoc, "expected relocatable expression with only one symbol");
2882 return true;
2883 }
2884
2885 // The case where the result register is $25 is somewhat special. If the
2886 // symbol in the final relocation is external and not modified with a
2887 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2888 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2889 Res.getConstant() == 0 &&
2890 !(Res.getSymA()->getSymbol().isInSection() ||
2891 Res.getSymA()->getSymbol().isTemporary() ||
2892 (Res.getSymA()->getSymbol().isELF() &&
2893 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2894 ELF::STB_LOCAL))) {
2895 const MCExpr *CallExpr =
2896 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2897 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2898 MCOperand::createExpr(CallExpr), IDLoc, STI);
2899 return false;
2900 }
2901
2902 // The remaining cases are:
2903 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2904 // >daddiu $tmp, $tmp, offset
2905 // >daddu $rd, $tmp, $rs
2906 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2907 // this happens then the last instruction must use $rd as the result
2908 // register.
2909 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2910 Res.getSymA(),
2911 getContext());
2912 const MCExpr *LoExpr = nullptr;
2913 if (Res.getConstant() != 0) {
2914 // Symbols fully resolve with just the %got_disp(symbol) but we
2915 // must still account for any offset to the symbol for
2916 // expressions like symbol+8.
2917 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2918
2919 // FIXME: Offsets greater than 16 bits are not yet implemented.
2920 // FIXME: The correct range is a 32-bit sign-extended number.
2921 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2922 Error(IDLoc, "macro instruction uses large offset, which is not "
2923 "currently supported");
2924 return true;
2925 }
2926 }
2927
2928 unsigned TmpReg = DstReg;
2929 if (UseSrcReg &&
2930 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2931 SrcReg)) {
2932 // If $rs is the same as $rd, we need to use AT.
2933 // If it is not available we exit.
2934 unsigned ATReg = getATReg(IDLoc);
2935 if (!ATReg)
2936 return true;
2937 TmpReg = ATReg;
2938 }
2939
2940 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2941 MCOperand::createExpr(GotExpr), IDLoc, STI);
2942
2943 if (LoExpr)
2944 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2945 IDLoc, STI);
2946
2947 if (UseSrcReg)
2948 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2949
2950 return false;
2951 }
2952
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002953 const MipsMCExpr *HiExpr =
2954 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2955 const MipsMCExpr *LoExpr =
2956 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002957
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002958 // This is the 64-bit symbol address expansion.
2959 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002960 // We need AT for the 64-bit expansion in the cases where the optional
2961 // source register is the destination register and for the superscalar
2962 // scheduled form.
2963 //
2964 // If it is not available we exit if the destination is the same as the
2965 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002966
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002967 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002968 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002969 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002970 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002971
Simon Dardis3aa8a902017-02-06 12:43:46 +00002972 bool RdRegIsRsReg =
2973 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
2974
2975 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
2976 unsigned ATReg = getATReg(IDLoc);
2977
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002978 // If $rs is the same as $rd:
2979 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2980 // daddiu $at, $at, %higher(sym)
2981 // dsll $at, $at, 16
2982 // daddiu $at, $at, %hi(sym)
2983 // dsll $at, $at, 16
2984 // daddiu $at, $at, %lo(sym)
2985 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002986 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2987 STI);
2988 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2989 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2990 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2991 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2992 IDLoc, STI);
2993 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2994 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2995 IDLoc, STI);
2996 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002997
2998 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00002999 } else if (canUseATReg() && !RdRegIsRsReg) {
3000 unsigned ATReg = getATReg(IDLoc);
3001
3002 // If the $rs is different from $rd or if $rs isn't specified and we
3003 // have $at available:
3004 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3005 // lui $at, %hi(sym)
3006 // daddiu $rd, $rd, %higher(sym)
3007 // daddiu $at, $at, %lo(sym)
3008 // dsll32 $rd, $rd, 0
3009 // daddu $rd, $rd, $at
3010 // (daddu $rd, $rd, $rs)
3011 //
3012 // Which is preferred for superscalar issue.
3013 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3014 STI);
3015 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3016 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3017 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3018 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3019 IDLoc, STI);
3020 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3021 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3022 if (UseSrcReg)
3023 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3024
3025 return false;
3026 } else if (!canUseATReg() && !RdRegIsRsReg) {
3027 // Otherwise, synthesize the address in the destination register
3028 // serially:
3029 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3030 // daddiu $rd, $rd, %higher(sym)
3031 // dsll $rd, $rd, 16
3032 // daddiu $rd, $rd, %hi(sym)
3033 // dsll $rd, $rd, 16
3034 // daddiu $rd, $rd, %lo(sym)
3035 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3036 STI);
3037 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3038 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3039 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3040 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3041 MCOperand::createExpr(HiExpr), IDLoc, STI);
3042 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3043 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3044 MCOperand::createExpr(LoExpr), IDLoc, STI);
3045 if (UseSrcReg)
3046 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3047
3048 return false;
3049 } else {
3050 // We have a case where SrcReg == DstReg and we don't have $at
3051 // available. We can't expand this case, so error out appropriately.
3052 assert(SrcReg == DstReg && !canUseATReg() &&
3053 "Could have expanded dla but didn't?");
3054 reportParseError(IDLoc,
3055 "pseudo-instruction requires $at, which is not available");
3056 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003057 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003058 }
3059
3060 // And now, the 32-bit symbol address expansion:
3061 // If $rs is the same as $rd:
3062 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3063 // ori $at, $at, %lo(sym)
3064 // addu $rd, $at, $rd
3065 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3066 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3067 // ori $rd, $rd, %lo(sym)
3068 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003069 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003070 if (UseSrcReg &&
3071 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003072 // If $rs is the same as $rd, we need to use AT.
3073 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003074 unsigned ATReg = getATReg(IDLoc);
3075 if (!ATReg)
3076 return true;
3077 TmpReg = ATReg;
3078 }
3079
Daniel Sandersa736b372016-04-29 13:33:12 +00003080 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3081 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3082 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003083
Toma Tabacufb9d1252015-06-22 12:08:39 +00003084 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003085 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003086 else
Scott Egerton24557012016-01-21 15:11:01 +00003087 assert(
3088 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003089
Toma Tabacu674825c2015-06-16 12:16:24 +00003090 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003091}
3092
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003093// Each double-precision register DO-D15 overlaps with two of the single
3094// precision registers F0-F31. As an example, all of the following hold true:
3095// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3096static unsigned nextReg(unsigned Reg) {
3097 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3098 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3099 switch (Reg) {
3100 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3101 case Mips::ZERO: return Mips::AT;
3102 case Mips::AT: return Mips::V0;
3103 case Mips::V0: return Mips::V1;
3104 case Mips::V1: return Mips::A0;
3105 case Mips::A0: return Mips::A1;
3106 case Mips::A1: return Mips::A2;
3107 case Mips::A2: return Mips::A3;
3108 case Mips::A3: return Mips::T0;
3109 case Mips::T0: return Mips::T1;
3110 case Mips::T1: return Mips::T2;
3111 case Mips::T2: return Mips::T3;
3112 case Mips::T3: return Mips::T4;
3113 case Mips::T4: return Mips::T5;
3114 case Mips::T5: return Mips::T6;
3115 case Mips::T6: return Mips::T7;
3116 case Mips::T7: return Mips::S0;
3117 case Mips::S0: return Mips::S1;
3118 case Mips::S1: return Mips::S2;
3119 case Mips::S2: return Mips::S3;
3120 case Mips::S3: return Mips::S4;
3121 case Mips::S4: return Mips::S5;
3122 case Mips::S5: return Mips::S6;
3123 case Mips::S6: return Mips::S7;
3124 case Mips::S7: return Mips::T8;
3125 case Mips::T8: return Mips::T9;
3126 case Mips::T9: return Mips::K0;
3127 case Mips::K0: return Mips::K1;
3128 case Mips::K1: return Mips::GP;
3129 case Mips::GP: return Mips::SP;
3130 case Mips::SP: return Mips::FP;
3131 case Mips::FP: return Mips::RA;
3132 case Mips::RA: return Mips::ZERO;
3133 case Mips::D0: return Mips::F1;
3134 case Mips::D1: return Mips::F3;
3135 case Mips::D2: return Mips::F5;
3136 case Mips::D3: return Mips::F7;
3137 case Mips::D4: return Mips::F9;
3138 case Mips::D5: return Mips::F11;
3139 case Mips::D6: return Mips::F13;
3140 case Mips::D7: return Mips::F15;
3141 case Mips::D8: return Mips::F17;
3142 case Mips::D9: return Mips::F19;
3143 case Mips::D10: return Mips::F21;
3144 case Mips::D11: return Mips::F23;
3145 case Mips::D12: return Mips::F25;
3146 case Mips::D13: return Mips::F27;
3147 case Mips::D14: return Mips::F29;
3148 case Mips::D15: return Mips::F31;
3149 }
3150}
3151
3152// FIXME: This method is too general. In principle we should compute the number
3153// of instructions required to synthesize the immediate inline compared to
3154// synthesizing the address inline and relying on non .text sections.
3155// For static O32 and N32 this may yield a small benefit, for static N64 this is
3156// likely to yield a much larger benefit as we have to synthesize a 64bit
3157// address to load a 64 bit value.
3158bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3159 MCSymbol *Sym) {
3160 unsigned ATReg = getATReg(IDLoc);
3161 if (!ATReg)
3162 return true;
3163
3164 if(IsPicEnabled) {
3165 const MCExpr *GotSym =
3166 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3167 const MipsMCExpr *GotExpr =
3168 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3169
3170 if(isABI_O32() || isABI_N32()) {
3171 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3172 IDLoc, STI);
3173 } else { //isABI_N64()
3174 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3175 IDLoc, STI);
3176 }
3177 } else { //!IsPicEnabled
3178 const MCExpr *HiSym =
3179 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3180 const MipsMCExpr *HiExpr =
3181 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3182
3183 // FIXME: This is technically correct but gives a different result to gas,
3184 // but gas is incomplete there (it has a fixme noting it doesn't work with
3185 // 64-bit addresses).
3186 // FIXME: With -msym32 option, the address expansion for N64 should probably
3187 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3188 // symbol's value is considered sign extended.
3189 if(isABI_O32() || isABI_N32()) {
3190 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3191 } else { //isABI_N64()
3192 const MCExpr *HighestSym =
3193 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3194 const MipsMCExpr *HighestExpr =
3195 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3196 const MCExpr *HigherSym =
3197 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3198 const MipsMCExpr *HigherExpr =
3199 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3200
3201 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3202 STI);
3203 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3204 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3205 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3206 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3207 IDLoc, STI);
3208 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3209 }
3210 }
3211 return false;
3212}
3213
3214bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3215 bool Is64FPU, SMLoc IDLoc,
3216 MCStreamer &Out,
3217 const MCSubtargetInfo *STI) {
3218 MipsTargetStreamer &TOut = getTargetStreamer();
3219 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3220 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3221 "Invalid instruction operand.");
3222
3223 unsigned FirstReg = Inst.getOperand(0).getReg();
3224 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3225
3226 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3227 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3228 // exponent field), convert it to double (e.g. 1 to 1.0)
3229 if ((HiImmOp64 & 0x7ff00000) == 0) {
3230 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3231 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3232 }
3233
3234 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3235 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3236
3237 if (IsSingle) {
3238 // Conversion of a double in an uint64_t to a float in a uint32_t,
3239 // retaining the bit pattern of a float.
3240 uint32_t ImmOp32;
3241 double doubleImm = BitsToDouble(ImmOp64);
3242 float tmp_float = static_cast<float>(doubleImm);
3243 ImmOp32 = FloatToBits(tmp_float);
3244
3245 if (IsGPR) {
3246 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3247 Out, STI))
3248 return true;
3249 return false;
3250 } else {
3251 unsigned ATReg = getATReg(IDLoc);
3252 if (!ATReg)
3253 return true;
3254 if (LoImmOp64 == 0) {
3255 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3256 Out, STI))
3257 return true;
3258 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3259 return false;
3260 }
3261
3262 MCSection *CS = getStreamer().getCurrentSectionOnly();
3263 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3264 // where appropriate.
3265 MCSection *ReadOnlySection = getContext().getELFSection(
3266 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3267
3268 MCSymbol *Sym = getContext().createTempSymbol();
3269 const MCExpr *LoSym =
3270 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3271 const MipsMCExpr *LoExpr =
3272 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3273
3274 getStreamer().SwitchSection(ReadOnlySection);
3275 getStreamer().EmitLabel(Sym, IDLoc);
3276 getStreamer().EmitIntValue(ImmOp32, 4);
3277 getStreamer().SwitchSection(CS);
3278
3279 if(emitPartialAddress(TOut, IDLoc, Sym))
3280 return true;
3281 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3282 MCOperand::createExpr(LoExpr), IDLoc, STI);
3283 }
3284 return false;
3285 }
3286
3287 // if(!IsSingle)
3288 unsigned ATReg = getATReg(IDLoc);
3289 if (!ATReg)
3290 return true;
3291
3292 if (IsGPR) {
3293 if (LoImmOp64 == 0) {
3294 if(isABI_N32() || isABI_N64()) {
3295 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3296 IDLoc, Out, STI))
3297 return true;
3298 return false;
3299 } else {
3300 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3301 IDLoc, Out, STI))
3302 return true;
3303
3304 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3305 IDLoc, Out, STI))
3306 return true;
3307 return false;
3308 }
3309 }
3310
3311 MCSection *CS = getStreamer().getCurrentSectionOnly();
3312 MCSection *ReadOnlySection = getContext().getELFSection(
3313 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3314
3315 MCSymbol *Sym = getContext().createTempSymbol();
3316 const MCExpr *LoSym =
3317 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3318 const MipsMCExpr *LoExpr =
3319 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3320
3321 getStreamer().SwitchSection(ReadOnlySection);
3322 getStreamer().EmitLabel(Sym, IDLoc);
3323 getStreamer().EmitIntValue(HiImmOp64, 4);
3324 getStreamer().EmitIntValue(LoImmOp64, 4);
3325 getStreamer().SwitchSection(CS);
3326
3327 if(emitPartialAddress(TOut, IDLoc, Sym))
3328 return true;
3329 if(isABI_N64())
3330 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3331 MCOperand::createExpr(LoExpr), IDLoc, STI);
3332 else
3333 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3334 MCOperand::createExpr(LoExpr), IDLoc, STI);
3335
3336 if(isABI_N32() || isABI_N64())
3337 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3338 else {
3339 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3340 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3341 }
3342 return false;
3343 } else { // if(!IsGPR && !IsSingle)
3344 if ((LoImmOp64 == 0) &&
3345 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3346 // FIXME: In the case where the constant is zero, we can load the
3347 // register directly from the zero register.
3348 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3349 Out, STI))
3350 return true;
3351 if (isABI_N32() || isABI_N64())
3352 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3353 else if (hasMips32r2()) {
3354 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3355 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3356 } else {
3357 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3358 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3359 }
3360 return false;
3361 }
3362
3363 MCSection *CS = getStreamer().getCurrentSectionOnly();
3364 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3365 // where appropriate.
3366 MCSection *ReadOnlySection = getContext().getELFSection(
3367 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3368
3369 MCSymbol *Sym = getContext().createTempSymbol();
3370 const MCExpr *LoSym =
3371 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3372 const MipsMCExpr *LoExpr =
3373 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3374
3375 getStreamer().SwitchSection(ReadOnlySection);
3376 getStreamer().EmitLabel(Sym, IDLoc);
3377 getStreamer().EmitIntValue(HiImmOp64, 4);
3378 getStreamer().EmitIntValue(LoImmOp64, 4);
3379 getStreamer().SwitchSection(CS);
3380
3381 if(emitPartialAddress(TOut, IDLoc, Sym))
3382 return true;
3383 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3384 MCOperand::createExpr(LoExpr), IDLoc, STI);
3385 }
3386 return false;
3387}
3388
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003389bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3390 MCStreamer &Out,
3391 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003392 MipsTargetStreamer &TOut = getTargetStreamer();
3393
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003394 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3395 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003396
3397 MCOperand Offset = Inst.getOperand(0);
3398 if (Offset.isExpr()) {
3399 Inst.clear();
3400 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003401 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3402 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3403 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003404 } else {
3405 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003406 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003407 // If offset fits into 11 bits then this instruction becomes microMIPS
3408 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003409 if (inMicroMipsMode())
3410 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003411 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003412 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003413 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003414 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003415 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003416 Inst.clear();
3417 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003418 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3419 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3420 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003421 }
3422 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003423 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003424
Zoran Jovanovicada70912015-09-07 11:56:37 +00003425 // If .set reorder is active and branch instruction has a delay slot,
3426 // emit a NOP after it.
3427 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3428 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003429 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003430
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003431 return false;
3432}
3433
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003434bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3435 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003436 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003437 const MCOperand &DstRegOp = Inst.getOperand(0);
3438 assert(DstRegOp.isReg() && "expected register operand kind");
3439
3440 const MCOperand &ImmOp = Inst.getOperand(1);
3441 assert(ImmOp.isImm() && "expected immediate operand kind");
3442
3443 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003444 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3445 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003446
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003447 bool IsLikely = false;
3448
Toma Tabacue1e460d2015-06-11 10:36:10 +00003449 unsigned OpCode = 0;
3450 switch(Inst.getOpcode()) {
3451 case Mips::BneImm:
3452 OpCode = Mips::BNE;
3453 break;
3454 case Mips::BeqImm:
3455 OpCode = Mips::BEQ;
3456 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003457 case Mips::BEQLImmMacro:
3458 OpCode = Mips::BEQL;
3459 IsLikely = true;
3460 break;
3461 case Mips::BNELImmMacro:
3462 OpCode = Mips::BNEL;
3463 IsLikely = true;
3464 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003465 default:
3466 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3467 break;
3468 }
3469
3470 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003471 if (ImmValue == 0) {
3472 if (IsLikely) {
3473 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3474 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3475 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3476 } else
3477 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3478 STI);
3479 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003480 warnIfNoMacro(IDLoc);
3481
3482 unsigned ATReg = getATReg(IDLoc);
3483 if (!ATReg)
3484 return true;
3485
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003486 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003487 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003488 return true;
3489
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003490 if (IsLikely) {
3491 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3492 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3493 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3494 } else
3495 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003496 }
3497 return false;
3498}
3499
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003500void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003501 const MCSubtargetInfo *STI, bool IsLoad,
3502 bool IsImmOpnd) {
3503 if (IsLoad) {
3504 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3505 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003506 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003507 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3508}
3509
3510void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3511 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3512 MipsTargetStreamer &TOut = getTargetStreamer();
3513
3514 unsigned DstReg = Inst.getOperand(0).getReg();
3515 unsigned BaseReg = Inst.getOperand(1).getReg();
3516
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003517 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003518 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3519 unsigned DstRegClassID =
3520 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3521 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3522 (DstRegClassID == Mips::GPR64RegClassID);
3523
3524 if (IsImmOpnd) {
3525 // Try to use DstReg as the temporary.
3526 if (IsGPR && (BaseReg != DstReg)) {
3527 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3528 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3529 STI);
3530 return;
3531 }
3532
Matheus Almeida7de68e72014-06-18 14:46:05 +00003533 // At this point we need AT to perform the expansions and we exit if it is
3534 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003535 unsigned ATReg = getATReg(IDLoc);
3536 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003537 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003538
3539 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3540 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3541 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003542 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003543
Daniel Sandersfba875f2016-04-29 13:43:45 +00003544 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003545 MCOperand LoOperand = MCOperand::createExpr(
3546 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3547 MCOperand HiOperand = MCOperand::createExpr(
3548 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003549
3550 // Try to use DstReg as the temporary.
3551 if (IsGPR && (BaseReg != DstReg)) {
3552 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3553 LoOperand, DstReg, IDLoc, STI);
3554 return;
3555 }
3556
3557 // At this point we need AT to perform the expansions and we exit if it is
3558 // not available.
3559 unsigned ATReg = getATReg(IDLoc);
3560 if (!ATReg)
3561 return;
3562
3563 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3564 LoOperand, ATReg, IDLoc, STI);
3565}
3566
3567void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3568 const MCSubtargetInfo *STI,
3569 bool IsImmOpnd) {
3570 MipsTargetStreamer &TOut = getTargetStreamer();
3571
3572 unsigned SrcReg = Inst.getOperand(0).getReg();
3573 unsigned BaseReg = Inst.getOperand(1).getReg();
3574
Daniel Sanders241c6792016-05-12 14:01:50 +00003575 if (IsImmOpnd) {
3576 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3577 Inst.getOperand(2).getImm(),
3578 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3579 return;
3580 }
3581
Daniel Sandersfba875f2016-04-29 13:43:45 +00003582 unsigned ATReg = getATReg(IDLoc);
3583 if (!ATReg)
3584 return;
3585
Daniel Sandersfba875f2016-04-29 13:43:45 +00003586 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003587 MCOperand LoOperand = MCOperand::createExpr(
3588 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3589 MCOperand HiOperand = MCOperand::createExpr(
3590 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003591 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3592 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003593}
3594
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003595bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3596 MCStreamer &Out,
3597 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003598 unsigned OpNum = Inst.getNumOperands();
3599 unsigned Opcode = Inst.getOpcode();
3600 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3601
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003602 assert(Inst.getOperand(OpNum - 1).isImm() &&
3603 Inst.getOperand(OpNum - 2).isReg() &&
3604 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003605
3606 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3607 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003608 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3609 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3610 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3611 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003612 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003613 if (inMicroMipsMode() && hasMips32r6())
3614 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3615 else
3616 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3617 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003618
3619 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003620 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003621 return false;
3622}
3623
Toma Tabacu1a108322015-06-17 13:20:24 +00003624bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003625 MCStreamer &Out,
3626 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003627 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003628 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003629 unsigned PseudoOpcode = Inst.getOpcode();
3630 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003631 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003632 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3633
3634 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003635 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003636
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003637 unsigned TrgReg;
3638 if (TrgOp.isReg())
3639 TrgReg = TrgOp.getReg();
3640 else if (TrgOp.isImm()) {
3641 warnIfNoMacro(IDLoc);
3642 EmittedNoMacroWarning = true;
3643
3644 TrgReg = getATReg(IDLoc);
3645 if (!TrgReg)
3646 return true;
3647
3648 switch(PseudoOpcode) {
3649 default:
3650 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3651 case Mips::BLTImmMacro:
3652 PseudoOpcode = Mips::BLT;
3653 break;
3654 case Mips::BLEImmMacro:
3655 PseudoOpcode = Mips::BLE;
3656 break;
3657 case Mips::BGEImmMacro:
3658 PseudoOpcode = Mips::BGE;
3659 break;
3660 case Mips::BGTImmMacro:
3661 PseudoOpcode = Mips::BGT;
3662 break;
3663 case Mips::BLTUImmMacro:
3664 PseudoOpcode = Mips::BLTU;
3665 break;
3666 case Mips::BLEUImmMacro:
3667 PseudoOpcode = Mips::BLEU;
3668 break;
3669 case Mips::BGEUImmMacro:
3670 PseudoOpcode = Mips::BGEU;
3671 break;
3672 case Mips::BGTUImmMacro:
3673 PseudoOpcode = Mips::BGTU;
3674 break;
3675 case Mips::BLTLImmMacro:
3676 PseudoOpcode = Mips::BLTL;
3677 break;
3678 case Mips::BLELImmMacro:
3679 PseudoOpcode = Mips::BLEL;
3680 break;
3681 case Mips::BGELImmMacro:
3682 PseudoOpcode = Mips::BGEL;
3683 break;
3684 case Mips::BGTLImmMacro:
3685 PseudoOpcode = Mips::BGTL;
3686 break;
3687 case Mips::BLTULImmMacro:
3688 PseudoOpcode = Mips::BLTUL;
3689 break;
3690 case Mips::BLEULImmMacro:
3691 PseudoOpcode = Mips::BLEUL;
3692 break;
3693 case Mips::BGEULImmMacro:
3694 PseudoOpcode = Mips::BGEUL;
3695 break;
3696 case Mips::BGTULImmMacro:
3697 PseudoOpcode = Mips::BGTUL;
3698 break;
3699 }
3700
3701 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003702 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003703 return true;
3704 }
3705
Toma Tabacu1a108322015-06-17 13:20:24 +00003706 switch (PseudoOpcode) {
3707 case Mips::BLT:
3708 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003709 case Mips::BLTL:
3710 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003711 AcceptsEquality = false;
3712 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003713 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3714 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003715 ZeroSrcOpcode = Mips::BGTZ;
3716 ZeroTrgOpcode = Mips::BLTZ;
3717 break;
3718 case Mips::BLE:
3719 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003720 case Mips::BLEL:
3721 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003722 AcceptsEquality = true;
3723 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003724 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3725 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003726 ZeroSrcOpcode = Mips::BGEZ;
3727 ZeroTrgOpcode = Mips::BLEZ;
3728 break;
3729 case Mips::BGE:
3730 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003731 case Mips::BGEL:
3732 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003733 AcceptsEquality = true;
3734 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003735 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3736 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003737 ZeroSrcOpcode = Mips::BLEZ;
3738 ZeroTrgOpcode = Mips::BGEZ;
3739 break;
3740 case Mips::BGT:
3741 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003742 case Mips::BGTL:
3743 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003744 AcceptsEquality = false;
3745 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003746 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3747 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003748 ZeroSrcOpcode = Mips::BLTZ;
3749 ZeroTrgOpcode = Mips::BGTZ;
3750 break;
3751 default:
3752 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3753 }
3754
Toma Tabacu1a108322015-06-17 13:20:24 +00003755 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3756 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3757 if (IsSrcRegZero && IsTrgRegZero) {
3758 // FIXME: All of these Opcode-specific if's are needed for compatibility
3759 // with GAS' behaviour. However, they may not generate the most efficient
3760 // code in some circumstances.
3761 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003762 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3763 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003764 return false;
3765 }
3766 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003767 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3768 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003769 Warning(IDLoc, "branch is always taken");
3770 return false;
3771 }
3772 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003773 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3774 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003775 Warning(IDLoc, "branch is always taken");
3776 return false;
3777 }
3778 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003779 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3780 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003781 return false;
3782 }
3783 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003784 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3785 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003786 return false;
3787 }
3788 if (AcceptsEquality) {
3789 // If both registers are $0 and the pseudo-branch accepts equality, it
3790 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003791 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3792 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003793 Warning(IDLoc, "branch is always taken");
3794 return false;
3795 }
3796 // If both registers are $0 and the pseudo-branch does not accept
3797 // equality, it will never be taken, so we don't have to emit anything.
3798 return false;
3799 }
3800 if (IsSrcRegZero || IsTrgRegZero) {
3801 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3802 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3803 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3804 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3805 // the pseudo-branch will never be taken, so we don't emit anything.
3806 // This only applies to unsigned pseudo-branches.
3807 return false;
3808 }
3809 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3810 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3811 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3812 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3813 // the pseudo-branch will always be taken, so we emit an unconditional
3814 // branch.
3815 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003816 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3817 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003818 Warning(IDLoc, "branch is always taken");
3819 return false;
3820 }
3821 if (IsUnsigned) {
3822 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3823 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3824 // the pseudo-branch will be taken only when the non-zero register is
3825 // different from 0, so we emit a BNEZ.
3826 //
3827 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3828 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3829 // the pseudo-branch will be taken only when the non-zero register is
3830 // equal to 0, so we emit a BEQZ.
3831 //
3832 // Because only BLEU and BGEU branch on equality, we can use the
3833 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003834 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3835 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3836 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003837 return false;
3838 }
3839 // If we have a signed pseudo-branch and one of the registers is $0,
3840 // we can use an appropriate compare-to-zero branch. We select which one
3841 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003842 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3843 IsSrcRegZero ? TrgReg : SrcReg,
3844 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003845 return false;
3846 }
3847
3848 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3849 // expansions. If it is not available, we return.
3850 unsigned ATRegNum = getATReg(IDLoc);
3851 if (!ATRegNum)
3852 return true;
3853
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003854 if (!EmittedNoMacroWarning)
3855 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003856
3857 // SLT fits well with 2 of our 4 pseudo-branches:
3858 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3859 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3860 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3861 // This is accomplished by using a BNEZ with the result of the SLT.
3862 //
3863 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3864 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3865 // Because only BGE and BLE branch on equality, we can use the
3866 // AcceptsEquality variable to decide when to emit the BEQZ.
3867 // Note that the order of the SLT arguments doesn't change between
3868 // opposites.
3869 //
3870 // The same applies to the unsigned variants, except that SLTu is used
3871 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003872 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3873 ReverseOrderSLT ? TrgReg : SrcReg,
3874 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003875
Daniel Sandersa736b372016-04-29 13:33:12 +00003876 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3877 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3878 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3879 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003880 return false;
3881}
3882
Simon Dardis509da1a2017-02-13 16:06:48 +00003883// Expand a integer division macro.
3884//
3885// Notably we don't have to emit a warning when encountering $rt as the $zero
3886// register, or 0 as an immediate. processInstruction() has already done that.
3887//
3888// The destination register can only be $zero when expanding (S)DivIMacro or
3889// D(S)DivMacro.
3890
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003891bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3892 const MCSubtargetInfo *STI, const bool IsMips64,
3893 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003894 MipsTargetStreamer &TOut = getTargetStreamer();
3895
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003896 warnIfNoMacro(IDLoc);
3897
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003898 const MCOperand &RdRegOp = Inst.getOperand(0);
3899 assert(RdRegOp.isReg() && "expected register operand kind");
3900 unsigned RdReg = RdRegOp.getReg();
3901
3902 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003903 assert(RsRegOp.isReg() && "expected register operand kind");
3904 unsigned RsReg = RsRegOp.getReg();
3905
Simon Dardis12850ee2017-01-31 10:49:24 +00003906 unsigned RtReg;
3907 int64_t ImmValue;
3908
3909 const MCOperand &RtOp = Inst.getOperand(2);
3910 assert((RtOp.isReg() || RtOp.isImm()) &&
3911 "expected register or immediate operand kind");
3912 if (RtOp.isReg())
3913 RtReg = RtOp.getReg();
3914 else
3915 ImmValue = RtOp.getImm();
3916
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003917 unsigned DivOp;
3918 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003919 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003920
3921 if (IsMips64) {
3922 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3923 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003924 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003925 } else {
3926 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3927 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003928 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003929 }
3930
3931 bool UseTraps = useTraps();
3932
Simon Dardis12850ee2017-01-31 10:49:24 +00003933 if (RtOp.isImm()) {
3934 unsigned ATReg = getATReg(IDLoc);
3935 if (!ATReg)
3936 return true;
3937
3938 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003939 if (UseTraps)
3940 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3941 else
3942 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3943 return false;
3944 }
3945
3946 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003947 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003948 return false;
3949 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003950 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003951 return false;
3952 } else {
3953 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3954 false, Inst.getLoc(), Out, STI))
3955 return true;
3956 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3957 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3958 return false;
3959 }
3960 return true;
3961 }
3962
Simon Dardis509da1a2017-02-13 16:06:48 +00003963 // If the macro expansion of (d)div(u) would always trap or break, insert
3964 // the trap/break and exit. This gives a different result to GAS. GAS has
3965 // an inconsistency/missed optimization in that not all cases are handled
3966 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003967 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003968 if (UseTraps) {
3969 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003970 return false;
3971 }
Simon Dardis509da1a2017-02-13 16:06:48 +00003972 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3973 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003974 }
3975
Simon Dardis509da1a2017-02-13 16:06:48 +00003976 // Temporary label for first branch traget
3977 MCContext &Context = TOut.getStreamer().getContext();
3978 MCSymbol *BrTarget;
3979 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003980
3981 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003982 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003983 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003984 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00003985 BrTarget = Context.createTempSymbol();
3986 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
3987 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003988 }
3989
Daniel Sandersa736b372016-04-29 13:33:12 +00003990 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003991
3992 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003993 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003994
3995 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003996 if (!UseTraps)
3997 TOut.getStreamer().EmitLabel(BrTarget);
3998
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003999 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004000 return false;
4001 }
4002
4003 unsigned ATReg = getATReg(IDLoc);
4004 if (!ATReg)
4005 return true;
4006
Simon Dardis509da1a2017-02-13 16:06:48 +00004007 if (!UseTraps)
4008 TOut.getStreamer().EmitLabel(BrTarget);
4009
Daniel Sandersa736b372016-04-29 13:33:12 +00004010 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004011
4012 // Temporary label for the second branch target.
4013 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4014 MCOperand LabelOpEnd =
4015 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4016
4017 // Branch to the mflo instruction.
4018 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4019
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004020 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004021 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4022 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004023 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004024 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004025 }
4026
4027 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004028 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004029 else {
4030 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004031 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004032 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4033 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004034 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004035
4036 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004037 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004038 return false;
4039}
4040
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004041bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004042 SMLoc IDLoc, MCStreamer &Out,
4043 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004044 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004045
4046 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4047 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4048 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4049
4050 unsigned FirstReg = Inst.getOperand(0).getReg();
4051 unsigned SecondReg = Inst.getOperand(1).getReg();
4052 unsigned ThirdReg = Inst.getOperand(2).getReg();
4053
4054 if (hasMips1() && !hasMips2()) {
4055 unsigned ATReg = getATReg(IDLoc);
4056 if (!ATReg)
4057 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004058 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4059 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4060 TOut.emitNop(IDLoc, STI);
4061 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4062 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4063 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4064 TOut.emitNop(IDLoc, STI);
4065 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4066 : Mips::CVT_W_S,
4067 FirstReg, SecondReg, IDLoc, STI);
4068 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4069 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004070 return false;
4071 }
4072
Daniel Sandersa736b372016-04-29 13:33:12 +00004073 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4074 : Mips::TRUNC_W_S,
4075 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004076
4077 return false;
4078}
4079
Daniel Sanders6394ee52015-10-15 14:52:58 +00004080bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004081 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004082 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004083 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004084 }
4085
Toma Tabacud88d79c2015-06-23 14:39:42 +00004086 const MCOperand &DstRegOp = Inst.getOperand(0);
4087 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004088 const MCOperand &SrcRegOp = Inst.getOperand(1);
4089 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004090 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4091 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4092
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004093 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004094 unsigned DstReg = DstRegOp.getReg();
4095 unsigned SrcReg = SrcRegOp.getReg();
4096 int64_t OffsetValue = OffsetImmOp.getImm();
4097
4098 // NOTE: We always need AT for ULHU, as it is always used as the source
4099 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004100 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004101 unsigned ATReg = getATReg(IDLoc);
4102 if (!ATReg)
4103 return true;
4104
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004105 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4106 if (IsLargeOffset) {
4107 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4108 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004109 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004110 }
4111
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004112 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4113 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4114 if (isLittle())
4115 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004116
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004117 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4118 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004119
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004120 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4121 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004122
Daniel Sandersa736b372016-04-29 13:33:12 +00004123 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004124 FirstOffset, IDLoc, STI);
4125 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004126 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004127 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004128
4129 return false;
4130}
4131
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004132bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004133 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004134 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004135 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004136 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004137
4138 const MCOperand &DstRegOp = Inst.getOperand(0);
4139 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004140 const MCOperand &SrcRegOp = Inst.getOperand(1);
4141 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004142 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4143 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4144
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004145 MipsTargetStreamer &TOut = getTargetStreamer();
4146 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004147 unsigned SrcReg = SrcRegOp.getReg();
4148 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004149
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004150 warnIfNoMacro(IDLoc);
4151 unsigned ATReg = getATReg(IDLoc);
4152 if (!ATReg)
4153 return true;
4154
4155 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4156 if (IsLargeOffset) {
4157 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4158 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004159 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004160 }
4161
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004162 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4163 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4164 if (isLittle())
4165 std::swap(FirstOffset, SecondOffset);
4166
4167 if (IsLargeOffset) {
4168 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4169 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4170 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4171 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4172 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4173 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004174 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004175 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4176 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4177 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004178 }
4179
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004180 return false;
4181}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004182
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004183bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4184 const MCSubtargetInfo *STI) {
4185 if (hasMips32r6() || hasMips64r6()) {
4186 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4187 }
4188
4189 const MCOperand &DstRegOp = Inst.getOperand(0);
4190 assert(DstRegOp.isReg() && "expected register operand kind");
4191 const MCOperand &SrcRegOp = Inst.getOperand(1);
4192 assert(SrcRegOp.isReg() && "expected register operand kind");
4193 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4194 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4195
4196 MipsTargetStreamer &TOut = getTargetStreamer();
4197 unsigned DstReg = DstRegOp.getReg();
4198 unsigned SrcReg = SrcRegOp.getReg();
4199 int64_t OffsetValue = OffsetImmOp.getImm();
4200
4201 // Compute left/right load/store offsets.
4202 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4203 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4204 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4205 if (isLittle())
4206 std::swap(LxlOffset, LxrOffset);
4207
4208 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4209 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4210 unsigned TmpReg = SrcReg;
4211 if (IsLargeOffset || DoMove) {
4212 warnIfNoMacro(IDLoc);
4213 TmpReg = getATReg(IDLoc);
4214 if (!TmpReg)
4215 return true;
4216 }
4217
4218 if (IsLargeOffset) {
4219 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4220 IDLoc, Out, STI))
4221 return true;
4222 }
4223
4224 if (DoMove)
4225 std::swap(DstReg, TmpReg);
4226
4227 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4228 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4229 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4230 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4231
4232 if (DoMove)
4233 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004234
4235 return false;
4236}
4237
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004238bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004239 MCStreamer &Out,
4240 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004241 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004242
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004243 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4244 assert(Inst.getOperand(0).isReg() &&
4245 Inst.getOperand(1).isReg() &&
4246 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004247
4248 unsigned ATReg = Mips::NoRegister;
4249 unsigned FinalDstReg = Mips::NoRegister;
4250 unsigned DstReg = Inst.getOperand(0).getReg();
4251 unsigned SrcReg = Inst.getOperand(1).getReg();
4252 int64_t ImmValue = Inst.getOperand(2).getImm();
4253
Simon Dardisaa208812017-02-24 14:34:32 +00004254 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004255
4256 unsigned FinalOpcode = Inst.getOpcode();
4257
4258 if (DstReg == SrcReg) {
4259 ATReg = getATReg(Inst.getLoc());
4260 if (!ATReg)
4261 return true;
4262 FinalDstReg = DstReg;
4263 DstReg = ATReg;
4264 }
4265
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004266 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004267 switch (FinalOpcode) {
4268 default:
4269 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004270 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004271 FinalOpcode = Mips::ADD;
4272 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004273 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004274 FinalOpcode = Mips::ADDu;
4275 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004276 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004277 FinalOpcode = Mips::AND;
4278 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004279 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004280 FinalOpcode = Mips::NOR;
4281 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004282 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004283 FinalOpcode = Mips::OR;
4284 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004285 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004286 FinalOpcode = Mips::SLT;
4287 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004288 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004289 FinalOpcode = Mips::SLTu;
4290 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004291 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004292 FinalOpcode = Mips::XOR;
4293 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004294 case Mips::ADDi_MM:
4295 FinalOpcode = Mips::ADD_MM;
4296 break;
4297 case Mips::ADDiu_MM:
4298 FinalOpcode = Mips::ADDu_MM;
4299 break;
4300 case Mips::ANDi_MM:
4301 FinalOpcode = Mips::AND_MM;
4302 break;
4303 case Mips::ORi_MM:
4304 FinalOpcode = Mips::OR_MM;
4305 break;
4306 case Mips::SLTi_MM:
4307 FinalOpcode = Mips::SLT_MM;
4308 break;
4309 case Mips::SLTiu_MM:
4310 FinalOpcode = Mips::SLTu_MM;
4311 break;
4312 case Mips::XORi_MM:
4313 FinalOpcode = Mips::XOR_MM;
4314 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004315 case Mips::ANDi64:
4316 FinalOpcode = Mips::AND64;
4317 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004318 case Mips::NORImm64:
4319 FinalOpcode = Mips::NOR64;
4320 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004321 case Mips::ORi64:
4322 FinalOpcode = Mips::OR64;
4323 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004324 case Mips::SLTImm64:
4325 FinalOpcode = Mips::SLT64;
4326 break;
4327 case Mips::SLTUImm64:
4328 FinalOpcode = Mips::SLTu64;
4329 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004330 case Mips::XORi64:
4331 FinalOpcode = Mips::XOR64;
4332 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004333 }
4334
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004335 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004336 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004337 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004338 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004339 return false;
4340 }
4341 return true;
4342}
4343
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004344bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4345 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004346 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004347 unsigned ATReg = Mips::NoRegister;
4348 unsigned DReg = Inst.getOperand(0).getReg();
4349 unsigned SReg = Inst.getOperand(1).getReg();
4350 unsigned TReg = Inst.getOperand(2).getReg();
4351 unsigned TmpReg = DReg;
4352
4353 unsigned FirstShift = Mips::NOP;
4354 unsigned SecondShift = Mips::NOP;
4355
4356 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004357 if (DReg == SReg) {
4358 TmpReg = getATReg(Inst.getLoc());
4359 if (!TmpReg)
4360 return true;
4361 }
4362
4363 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004364 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4365 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004366 return false;
4367 }
4368
4369 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004370 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004371 return false;
4372 }
4373
4374 return true;
4375 }
4376
4377 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004378 switch (Inst.getOpcode()) {
4379 default:
4380 llvm_unreachable("unexpected instruction opcode");
4381 case Mips::ROL:
4382 FirstShift = Mips::SRLV;
4383 SecondShift = Mips::SLLV;
4384 break;
4385 case Mips::ROR:
4386 FirstShift = Mips::SLLV;
4387 SecondShift = Mips::SRLV;
4388 break;
4389 }
4390
4391 ATReg = getATReg(Inst.getLoc());
4392 if (!ATReg)
4393 return true;
4394
Daniel Sandersa736b372016-04-29 13:33:12 +00004395 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4396 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4397 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4398 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004399
4400 return false;
4401 }
4402
4403 return true;
4404}
4405
4406bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004407 MCStreamer &Out,
4408 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004409 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004410 unsigned ATReg = Mips::NoRegister;
4411 unsigned DReg = Inst.getOperand(0).getReg();
4412 unsigned SReg = Inst.getOperand(1).getReg();
4413 int64_t ImmValue = Inst.getOperand(2).getImm();
4414
4415 unsigned FirstShift = Mips::NOP;
4416 unsigned SecondShift = Mips::NOP;
4417
4418 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004419 if (Inst.getOpcode() == Mips::ROLImm) {
4420 uint64_t MaxShift = 32;
4421 uint64_t ShiftValue = ImmValue;
4422 if (ImmValue != 0)
4423 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004424 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004425 return false;
4426 }
4427
4428 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004429 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004430 return false;
4431 }
4432
4433 return true;
4434 }
4435
4436 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004437 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004438 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004439 return false;
4440 }
4441
4442 switch (Inst.getOpcode()) {
4443 default:
4444 llvm_unreachable("unexpected instruction opcode");
4445 case Mips::ROLImm:
4446 FirstShift = Mips::SLL;
4447 SecondShift = Mips::SRL;
4448 break;
4449 case Mips::RORImm:
4450 FirstShift = Mips::SRL;
4451 SecondShift = Mips::SLL;
4452 break;
4453 }
4454
4455 ATReg = getATReg(Inst.getLoc());
4456 if (!ATReg)
4457 return true;
4458
Daniel Sandersa736b372016-04-29 13:33:12 +00004459 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4460 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4461 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004462
4463 return false;
4464 }
4465
4466 return true;
4467}
4468
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004469bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4470 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004471 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004472 unsigned ATReg = Mips::NoRegister;
4473 unsigned DReg = Inst.getOperand(0).getReg();
4474 unsigned SReg = Inst.getOperand(1).getReg();
4475 unsigned TReg = Inst.getOperand(2).getReg();
4476 unsigned TmpReg = DReg;
4477
4478 unsigned FirstShift = Mips::NOP;
4479 unsigned SecondShift = Mips::NOP;
4480
4481 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004482 if (TmpReg == SReg) {
4483 TmpReg = getATReg(Inst.getLoc());
4484 if (!TmpReg)
4485 return true;
4486 }
4487
4488 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004489 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4490 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004491 return false;
4492 }
4493
4494 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004495 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004496 return false;
4497 }
4498
4499 return true;
4500 }
4501
4502 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004503 switch (Inst.getOpcode()) {
4504 default:
4505 llvm_unreachable("unexpected instruction opcode");
4506 case Mips::DROL:
4507 FirstShift = Mips::DSRLV;
4508 SecondShift = Mips::DSLLV;
4509 break;
4510 case Mips::DROR:
4511 FirstShift = Mips::DSLLV;
4512 SecondShift = Mips::DSRLV;
4513 break;
4514 }
4515
4516 ATReg = getATReg(Inst.getLoc());
4517 if (!ATReg)
4518 return true;
4519
Daniel Sandersa736b372016-04-29 13:33:12 +00004520 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4521 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4522 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4523 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004524
4525 return false;
4526 }
4527
4528 return true;
4529}
4530
4531bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004532 MCStreamer &Out,
4533 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004534 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004535 unsigned ATReg = Mips::NoRegister;
4536 unsigned DReg = Inst.getOperand(0).getReg();
4537 unsigned SReg = Inst.getOperand(1).getReg();
4538 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4539
4540 unsigned FirstShift = Mips::NOP;
4541 unsigned SecondShift = Mips::NOP;
4542
4543 MCInst TmpInst;
4544
4545 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004546 unsigned FinalOpcode = Mips::NOP;
4547 if (ImmValue == 0)
4548 FinalOpcode = Mips::DROTR;
4549 else if (ImmValue % 32 == 0)
4550 FinalOpcode = Mips::DROTR32;
4551 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4552 if (Inst.getOpcode() == Mips::DROLImm)
4553 FinalOpcode = Mips::DROTR32;
4554 else
4555 FinalOpcode = Mips::DROTR;
4556 } else if (ImmValue >= 33) {
4557 if (Inst.getOpcode() == Mips::DROLImm)
4558 FinalOpcode = Mips::DROTR;
4559 else
4560 FinalOpcode = Mips::DROTR32;
4561 }
4562
4563 uint64_t ShiftValue = ImmValue % 32;
4564 if (Inst.getOpcode() == Mips::DROLImm)
4565 ShiftValue = (32 - ImmValue % 32) % 32;
4566
Daniel Sandersa736b372016-04-29 13:33:12 +00004567 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004568
4569 return false;
4570 }
4571
4572 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004573 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004574 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004575 return false;
4576 }
4577
4578 switch (Inst.getOpcode()) {
4579 default:
4580 llvm_unreachable("unexpected instruction opcode");
4581 case Mips::DROLImm:
4582 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4583 FirstShift = Mips::DSLL;
4584 SecondShift = Mips::DSRL32;
4585 }
4586 if (ImmValue == 32) {
4587 FirstShift = Mips::DSLL32;
4588 SecondShift = Mips::DSRL32;
4589 }
4590 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4591 FirstShift = Mips::DSLL32;
4592 SecondShift = Mips::DSRL;
4593 }
4594 break;
4595 case Mips::DRORImm:
4596 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4597 FirstShift = Mips::DSRL;
4598 SecondShift = Mips::DSLL32;
4599 }
4600 if (ImmValue == 32) {
4601 FirstShift = Mips::DSRL32;
4602 SecondShift = Mips::DSLL32;
4603 }
4604 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4605 FirstShift = Mips::DSRL32;
4606 SecondShift = Mips::DSLL;
4607 }
4608 break;
4609 }
4610
4611 ATReg = getATReg(Inst.getLoc());
4612 if (!ATReg)
4613 return true;
4614
Daniel Sandersa736b372016-04-29 13:33:12 +00004615 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4616 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4617 Inst.getLoc(), STI);
4618 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004619
4620 return false;
4621 }
4622
4623 return true;
4624}
4625
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004626bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4627 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004628 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004629 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4630 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4631
Daniel Sandersa736b372016-04-29 13:33:12 +00004632 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004633 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004634 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004635 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004636 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4637 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004638
4639 return false;
4640}
4641
Simon Dardis3c82a642017-02-08 16:25:05 +00004642bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4643 const MCSubtargetInfo *STI) {
4644 MipsTargetStreamer &TOut = getTargetStreamer();
4645 unsigned ATReg = Mips::NoRegister;
4646 unsigned DstReg = Inst.getOperand(0).getReg();
4647 unsigned SrcReg = Inst.getOperand(1).getReg();
4648 int32_t ImmValue = Inst.getOperand(2).getImm();
4649
4650 ATReg = getATReg(IDLoc);
4651 if (!ATReg)
4652 return true;
4653
4654 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4655
4656 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4657 SrcReg, ATReg, IDLoc, STI);
4658
4659 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4660
4661 return false;
4662}
4663
4664bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4665 const MCSubtargetInfo *STI) {
4666 MipsTargetStreamer &TOut = getTargetStreamer();
4667 unsigned ATReg = Mips::NoRegister;
4668 unsigned DstReg = Inst.getOperand(0).getReg();
4669 unsigned SrcReg = Inst.getOperand(1).getReg();
4670 unsigned TmpReg = Inst.getOperand(2).getReg();
4671
4672 ATReg = getATReg(Inst.getLoc());
4673 if (!ATReg)
4674 return true;
4675
4676 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4677 SrcReg, TmpReg, IDLoc, STI);
4678
4679 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4680
4681 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4682 DstReg, DstReg, 0x1F, IDLoc, STI);
4683
4684 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4685
4686 if (useTraps()) {
4687 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4688 } else {
4689 MCContext & Context = TOut.getStreamer().getContext();
4690 MCSymbol * BrTarget = Context.createTempSymbol();
4691 MCOperand LabelOp =
4692 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4693
4694 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4695 if (AssemblerOptions.back()->isReorder())
4696 TOut.emitNop(IDLoc, STI);
4697 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4698
4699 TOut.getStreamer().EmitLabel(BrTarget);
4700 }
4701 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4702
4703 return false;
4704}
4705
4706bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4707 const MCSubtargetInfo *STI) {
4708 MipsTargetStreamer &TOut = getTargetStreamer();
4709 unsigned ATReg = Mips::NoRegister;
4710 unsigned DstReg = Inst.getOperand(0).getReg();
4711 unsigned SrcReg = Inst.getOperand(1).getReg();
4712 unsigned TmpReg = Inst.getOperand(2).getReg();
4713
4714 ATReg = getATReg(IDLoc);
4715 if (!ATReg)
4716 return true;
4717
4718 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4719 SrcReg, TmpReg, IDLoc, STI);
4720
4721 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4722 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4723 if (useTraps()) {
4724 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4725 } else {
4726 MCContext & Context = TOut.getStreamer().getContext();
4727 MCSymbol * BrTarget = Context.createTempSymbol();
4728 MCOperand LabelOp =
4729 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4730
4731 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4732 if (AssemblerOptions.back()->isReorder())
4733 TOut.emitNop(IDLoc, STI);
4734 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4735
4736 TOut.getStreamer().EmitLabel(BrTarget);
4737 }
4738
4739 return false;
4740}
4741
4742bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4743 const MCSubtargetInfo *STI) {
4744 MipsTargetStreamer &TOut = getTargetStreamer();
4745 unsigned DstReg = Inst.getOperand(0).getReg();
4746 unsigned SrcReg = Inst.getOperand(1).getReg();
4747 unsigned TmpReg = Inst.getOperand(2).getReg();
4748
4749 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4750 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4751
4752 return false;
4753}
4754
Simon Dardisaff4d142016-10-18 14:28:00 +00004755// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4756// lw $<reg+1>>, offset+4($reg2)'
4757// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4758// sw $<reg+1>>, offset+4($reg2)'
4759// for O32.
4760bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4761 MCStreamer &Out,
4762 const MCSubtargetInfo *STI,
4763 bool IsLoad) {
4764 if (!isABI_O32())
4765 return true;
4766
4767 warnIfNoMacro(IDLoc);
4768
4769 MipsTargetStreamer &TOut = getTargetStreamer();
4770 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4771 unsigned FirstReg = Inst.getOperand(0).getReg();
4772 unsigned SecondReg = nextReg(FirstReg);
4773 unsigned BaseReg = Inst.getOperand(1).getReg();
4774 if (!SecondReg)
4775 return true;
4776
4777 warnIfRegIndexIsAT(FirstReg, IDLoc);
4778
4779 assert(Inst.getOperand(2).isImm() &&
4780 "Offset for load macro is not immediate!");
4781
4782 MCOperand &FirstOffset = Inst.getOperand(2);
4783 signed NextOffset = FirstOffset.getImm() + 4;
4784 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4785
4786 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4787 return true;
4788
4789 // For loads, clobber the base register with the second load instead of the
4790 // first if the BaseReg == FirstReg.
4791 if (FirstReg != BaseReg || !IsLoad) {
4792 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4793 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4794 } else {
4795 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4796 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4797 }
4798
4799 return false;
4800}
4801
Simon Dardis43115a12016-11-21 20:30:41 +00004802bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4803 const MCSubtargetInfo *STI) {
4804
4805 warnIfNoMacro(IDLoc);
4806 MipsTargetStreamer &TOut = getTargetStreamer();
4807
4808 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4809 Inst.getOperand(2).getReg() != Mips::ZERO) {
4810 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4811 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4812 IDLoc, STI);
4813 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4814 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4815 return false;
4816 }
4817
4818 unsigned Reg = 0;
4819 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4820 Reg = Inst.getOperand(2).getReg();
4821 } else {
4822 Reg = Inst.getOperand(1).getReg();
4823 }
4824 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4825 return false;
4826}
4827
4828bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4829 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004830 warnIfNoMacro(IDLoc);
4831 MipsTargetStreamer &TOut = getTargetStreamer();
4832
4833 unsigned Opc;
4834 int64_t Imm = Inst.getOperand(2).getImm();
4835 unsigned Reg = Inst.getOperand(1).getReg();
4836
4837 if (Imm == 0) {
4838 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4839 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4840 return false;
4841 } else {
4842
4843 if (Reg == Mips::ZERO) {
4844 Warning(IDLoc, "comparison is always false");
4845 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4846 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4847 return false;
4848 }
4849
4850 if (Imm > -0x8000 && Imm < 0) {
4851 Imm = -Imm;
4852 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4853 } else {
4854 Opc = Mips::XORi;
4855 }
4856 }
4857 if (!isUInt<16>(Imm)) {
4858 unsigned ATReg = getATReg(IDLoc);
4859 if (!ATReg)
4860 return true;
4861
4862 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4863 Out, STI))
4864 return true;
4865
4866 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4867 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4868 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4869 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4870 return false;
4871 }
4872
4873 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4874 Imm, IDLoc, STI);
4875 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4876 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4877 return false;
4878}
4879
Daniel Sandersc5537422016-07-27 13:49:44 +00004880unsigned
4881MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4882 const OperandVector &Operands) {
4883 switch (Inst.getOpcode()) {
4884 default:
4885 return Match_Success;
4886 case Mips::DATI:
4887 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004888 case Mips::DATI_MM64R6:
4889 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004890 if (static_cast<MipsOperand &>(*Operands[1])
4891 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4892 return Match_Success;
4893 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004894 }
4895}
Simon Dardis730fdb72017-01-16 13:55:58 +00004896
Matheus Almeida595fcab2014-06-11 15:05:56 +00004897unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004898 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004899 // As described by the MIPSR6 spec, daui must not use the zero operand for
4900 // its source operand.
4901 case Mips::DAUI:
4902 case Mips::DAUI_MM64R6:
4903 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4904 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4905 return Match_RequiresNoZeroRegister;
4906 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004907 // As described by the Mips32r2 spec, the registers Rd and Rs for
4908 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004909 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004910 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004911 case Mips::JALR_HB:
4912 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004913 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004914 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4915 return Match_RequiresDifferentSrcAndDst;
4916 return Match_Success;
4917 case Mips::LWP_MM:
4918 case Mips::LWP_MMR6:
4919 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4920 return Match_RequiresDifferentSrcAndDst;
4921 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004922 case Mips::SYNC:
4923 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4924 return Match_NonZeroOperandForSync;
4925 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004926 // As described the MIPSR6 spec, the compact branches that compare registers
4927 // must:
4928 // a) Not use the zero register.
4929 // b) Not use the same register twice.
4930 // c) rs < rt for bnec, beqc.
4931 // NB: For this case, the encoding will swap the operands as their
4932 // ordering doesn't matter. GAS performs this transformation too.
4933 // Hence, that constraint does not have to be enforced.
4934 //
4935 // The compact branches that branch iff the signed addition of two registers
4936 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4937 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004938 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4939 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4940 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4941 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4942 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4943 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004944 case Mips::BLEZC64:
4945 case Mips::BGEZC64:
4946 case Mips::BGTZC64:
4947 case Mips::BLTZC64:
4948 case Mips::BEQZC64:
4949 case Mips::BNEZC64:
4950 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4951 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004952 return Match_RequiresNoZeroRegister;
4953 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004954 case Mips::BGEC: case Mips::BGEC_MMR6:
4955 case Mips::BLTC: case Mips::BLTC_MMR6:
4956 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4957 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4958 case Mips::BEQC: case Mips::BEQC_MMR6:
4959 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004960 case Mips::BGEC64:
4961 case Mips::BLTC64:
4962 case Mips::BGEUC64:
4963 case Mips::BLTUC64:
4964 case Mips::BEQC64:
4965 case Mips::BNEC64:
4966 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4967 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004968 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004969 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4970 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004971 return Match_RequiresNoZeroRegister;
4972 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4973 return Match_RequiresDifferentOperands;
4974 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004975 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004976
4977 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4978 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4979 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4980 return Match_NoFCCRegisterForCurrentISA;
4981
4982 return Match_Success;
4983
Matheus Almeida595fcab2014-06-11 15:05:56 +00004984}
4985
Daniel Sanders52da7af2015-11-06 12:11:03 +00004986static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4987 uint64_t ErrorInfo) {
4988 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4989 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4990 if (ErrorLoc == SMLoc())
4991 return Loc;
4992 return ErrorLoc;
4993 }
4994 return Loc;
4995}
4996
David Blaikie960ea3f2014-06-08 16:18:35 +00004997bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4998 OperandVector &Operands,
4999 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005000 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005001 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005002 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005003 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005004 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005005
5006 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005007 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005008 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005009 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005010 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005011 case Match_MissingFeature:
5012 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5013 return true;
5014 case Match_InvalidOperand: {
5015 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005016 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005017 if (ErrorInfo >= Operands.size())
5018 return Error(IDLoc, "too few operands for instruction");
5019
Daniel Sanders52da7af2015-11-06 12:11:03 +00005020 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005021 if (ErrorLoc == SMLoc())
5022 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005023 }
5024
5025 return Error(ErrorLoc, "invalid operand for instruction");
5026 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005027 case Match_NonZeroOperandForSync:
5028 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005029 case Match_MnemonicFail:
5030 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005031 case Match_RequiresDifferentSrcAndDst:
5032 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005033 case Match_RequiresDifferentOperands:
5034 return Error(IDLoc, "registers must be different");
5035 case Match_RequiresNoZeroRegister:
5036 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005037 case Match_RequiresSameSrcAndDst:
5038 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005039 case Match_NoFCCRegisterForCurrentISA:
5040 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5041 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005042 case Match_Immz:
5043 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005044 case Match_UImm1_0:
5045 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5046 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005047 case Match_UImm2_0:
5048 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5049 "expected 2-bit unsigned immediate");
5050 case Match_UImm2_1:
5051 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5052 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005053 case Match_UImm3_0:
5054 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5055 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005056 case Match_UImm4_0:
5057 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5058 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005059 case Match_SImm4_0:
5060 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5061 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005062 case Match_UImm5_0:
5063 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5064 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005065 case Match_SImm5_0:
5066 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5067 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005068 case Match_UImm5_1:
5069 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5070 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005071 case Match_UImm5_32:
5072 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5073 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005074 case Match_UImm5_33:
5075 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5076 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005077 case Match_UImm5_0_Report_UImm6:
5078 // This is used on UImm5 operands that have a corresponding UImm5_32
5079 // operand to avoid confusing the user.
5080 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5081 "expected 6-bit unsigned immediate");
5082 case Match_UImm5_Lsl2:
5083 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5084 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005085 case Match_UImmRange2_64:
5086 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5087 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005088 case Match_UImm6_0:
5089 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5090 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005091 case Match_UImm6_Lsl2:
5092 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5093 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005094 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005095 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5096 "expected 6-bit signed immediate");
5097 case Match_UImm7_0:
5098 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5099 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005100 case Match_UImm7_N1:
5101 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5102 "expected immediate in range -1 .. 126");
5103 case Match_SImm7_Lsl2:
5104 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5105 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005106 case Match_UImm8_0:
5107 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5108 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005109 case Match_UImm10_0:
5110 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5111 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005112 case Match_SImm10_0:
5113 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5114 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005115 case Match_SImm11_0:
5116 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5117 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005118 case Match_UImm16:
5119 case Match_UImm16_Relaxed:
5120 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5121 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005122 case Match_SImm16:
5123 case Match_SImm16_Relaxed:
5124 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5125 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005126 case Match_SImm19_Lsl2:
5127 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5128 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005129 case Match_UImm20_0:
5130 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5131 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005132 case Match_UImm26_0:
5133 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5134 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005135 case Match_SImm32:
5136 case Match_SImm32_Relaxed:
5137 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5138 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005139 case Match_UImm32_Coerced:
5140 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5141 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005142 case Match_MemSImm9:
5143 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5144 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005145 case Match_MemSImm10:
5146 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5147 "expected memory with 10-bit signed offset");
5148 case Match_MemSImm10Lsl1:
5149 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5150 "expected memory with 11-bit signed offset and multiple of 2");
5151 case Match_MemSImm10Lsl2:
5152 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5153 "expected memory with 12-bit signed offset and multiple of 4");
5154 case Match_MemSImm10Lsl3:
5155 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5156 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005157 case Match_MemSImm11:
5158 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5159 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005160 case Match_MemSImm12:
5161 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5162 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005163 case Match_MemSImm16:
5164 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5165 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00005166 }
Craig Topper589ceee2015-01-03 08:16:34 +00005167
5168 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005169}
5170
Toma Tabacud9d344b2015-04-27 14:05:04 +00005171void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5172 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5173 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5174 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005175}
5176
Toma Tabacu81496c12015-05-20 08:54:45 +00005177void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5178 if (!AssemblerOptions.back()->isMacro())
5179 Warning(Loc, "macro instruction expanded into multiple instructions");
5180}
5181
Daniel Sandersef638fe2014-10-03 15:37:37 +00005182void
5183MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5184 SMRange Range, bool ShowColors) {
5185 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005186 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005187 ShowColors);
5188}
5189
Jack Carter1ac53222013-02-20 23:11:17 +00005190int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005191 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005192
Vladimir Medic4c299852013-11-06 11:27:05 +00005193 CC = StringSwitch<unsigned>(Name)
5194 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005195 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005196 .Case("a0", 4)
5197 .Case("a1", 5)
5198 .Case("a2", 6)
5199 .Case("a3", 7)
5200 .Case("v0", 2)
5201 .Case("v1", 3)
5202 .Case("s0", 16)
5203 .Case("s1", 17)
5204 .Case("s2", 18)
5205 .Case("s3", 19)
5206 .Case("s4", 20)
5207 .Case("s5", 21)
5208 .Case("s6", 22)
5209 .Case("s7", 23)
5210 .Case("k0", 26)
5211 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005212 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005213 .Case("sp", 29)
5214 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005215 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005216 .Case("ra", 31)
5217 .Case("t0", 8)
5218 .Case("t1", 9)
5219 .Case("t2", 10)
5220 .Case("t3", 11)
5221 .Case("t4", 12)
5222 .Case("t5", 13)
5223 .Case("t6", 14)
5224 .Case("t7", 15)
5225 .Case("t8", 24)
5226 .Case("t9", 25)
5227 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005228
Toma Tabacufda445c2014-09-15 15:33:01 +00005229 if (!(isABI_N32() || isABI_N64()))
5230 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005231
Daniel Sandersef638fe2014-10-03 15:37:37 +00005232 if (12 <= CC && CC <= 15) {
5233 // Name is one of t4-t7
5234 AsmToken RegTok = getLexer().peekTok();
5235 SMRange RegRange = RegTok.getLocRange();
5236
5237 StringRef FixedName = StringSwitch<StringRef>(Name)
5238 .Case("t4", "t0")
5239 .Case("t5", "t1")
5240 .Case("t6", "t2")
5241 .Case("t7", "t3")
5242 .Default("");
5243 assert(FixedName != "" && "Register name is not one of t4-t7.");
5244
5245 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5246 "Did you mean $" + FixedName + "?", RegRange);
5247 }
5248
Toma Tabacufda445c2014-09-15 15:33:01 +00005249 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5250 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5251 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5252 if (8 <= CC && CC <= 11)
5253 CC += 4;
5254
5255 if (CC == -1)
5256 CC = StringSwitch<unsigned>(Name)
5257 .Case("a4", 8)
5258 .Case("a5", 9)
5259 .Case("a6", 10)
5260 .Case("a7", 11)
5261 .Case("kt0", 26)
5262 .Case("kt1", 27)
5263 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005264
5265 return CC;
5266}
Jack Carterd0bd6422013-04-18 00:41:53 +00005267
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005268int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5269 int CC;
5270
5271 CC = StringSwitch<unsigned>(Name)
5272 .Case("hwr_cpunum", 0)
5273 .Case("hwr_synci_step", 1)
5274 .Case("hwr_cc", 2)
5275 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005276 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005277 .Default(-1);
5278
5279 return CC;
5280}
5281
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005282int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005283 if (Name[0] == 'f') {
5284 StringRef NumString = Name.substr(1);
5285 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005286 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005287 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005288 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005289 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005290 return IntVal;
5291 }
5292 return -1;
5293}
Jack Cartera63b16a2012-09-07 00:23:42 +00005294
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005295int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005296 if (Name.startswith("fcc")) {
5297 StringRef NumString = Name.substr(3);
5298 unsigned IntVal;
5299 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005300 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005301 if (IntVal > 7) // There are only 8 fcc registers.
5302 return -1;
5303 return IntVal;
5304 }
5305 return -1;
5306}
5307
5308int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005309 if (Name.startswith("ac")) {
5310 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005311 unsigned IntVal;
5312 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005313 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005314 if (IntVal > 3) // There are only 3 acc registers.
5315 return -1;
5316 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005317 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005318 return -1;
5319}
Jack Carterd0bd6422013-04-18 00:41:53 +00005320
Jack Carter5dc8ac92013-09-25 23:50:44 +00005321int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5322 unsigned IntVal;
5323
5324 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5325 return -1;
5326
5327 if (IntVal > 31)
5328 return -1;
5329
5330 return IntVal;
5331}
5332
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005333int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5334 int CC;
5335
5336 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005337 .Case("msair", 0)
5338 .Case("msacsr", 1)
5339 .Case("msaaccess", 2)
5340 .Case("msasave", 3)
5341 .Case("msamodify", 4)
5342 .Case("msarequest", 5)
5343 .Case("msamap", 6)
5344 .Case("msaunmap", 7)
5345 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005346
5347 return CC;
5348}
5349
Simon Dardis3aa8a902017-02-06 12:43:46 +00005350bool MipsAsmParser::canUseATReg() {
5351 return AssemblerOptions.back()->getATRegIndex() != 0;
5352}
5353
Toma Tabacu89a712b2015-04-15 10:48:56 +00005354unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005355 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005356 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005357 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005358 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005359 return 0;
5360 }
5361 unsigned AT = getReg(
5362 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005363 return AT;
5364}
Jack Carter0b744b32012-10-04 02:29:46 +00005365
Jack Carterd0bd6422013-04-18 00:41:53 +00005366unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005367 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005368}
5369
Toma Tabacu13964452014-09-04 13:23:44 +00005370bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005371 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005372 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005373
Jack Carter30a59822012-10-04 04:03:53 +00005374 // Check if the current operand has a custom associated parser, if so, try to
5375 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005376 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5377 if (ResTy == MatchOperand_Success)
5378 return false;
5379 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5380 // there was a match, but an error occurred, in which case, just return that
5381 // the operand parsing failed.
5382 if (ResTy == MatchOperand_ParseFail)
5383 return true;
5384
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005385 DEBUG(dbgs() << ".. Generic Parser\n");
5386
Jack Carterb4dbc172012-09-05 23:34:03 +00005387 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005388 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005389 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005390 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005391
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005392 // Almost all registers have been parsed by custom parsers. There is only
5393 // one exception to this. $zero (and it's alias $0) will reach this point
5394 // for div, divu, and similar instructions because it is not an operand
5395 // to the instruction definition but an explicit register. Special case
5396 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005397 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005398 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005399
Jack Carterd0bd6422013-04-18 00:41:53 +00005400 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005401 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005402 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005403 return true;
5404
Jack Carter873c7242013-01-12 01:03:14 +00005405 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005406 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005407 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005408 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005409 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005410
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005411 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005412 return false;
5413 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005414 default: {
5415 DEBUG(dbgs() << ".. generic integer expression\n");
5416
5417 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005418 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005419 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005420 return true;
5421
Jack Carter873c7242013-01-12 01:03:14 +00005422 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5423
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005424 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005425 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005426 }
Jack Carter0b744b32012-10-04 02:29:46 +00005427 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005428 return true;
5429}
5430
Jack Carterb5cf5902013-04-17 00:18:04 +00005431bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005432 switch (Expr->getKind()) {
5433 case MCExpr::Constant:
5434 return true;
5435 case MCExpr::SymbolRef:
5436 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
5437 case MCExpr::Binary:
5438 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
5439 if (!isEvaluated(BE->getLHS()))
5440 return false;
5441 return isEvaluated(BE->getRHS());
5442 }
5443 case MCExpr::Unary:
5444 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005445 case MCExpr::Target:
5446 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005447 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005448 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005449}
Jack Carterd0bd6422013-04-18 00:41:53 +00005450
Jack Carterb4dbc172012-09-05 23:34:03 +00005451bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5452 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005453 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005454 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005455 if (ResTy == MatchOperand_Success) {
5456 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005457 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005458 StartLoc = Operand.getStartLoc();
5459 EndLoc = Operand.getEndLoc();
5460
5461 // AFAIK, we only support numeric registers and named GPR's in CFI
5462 // directives.
5463 // Don't worry about eating tokens before failing. Using an unrecognised
5464 // register is a parse error.
5465 if (Operand.isGPRAsmReg()) {
5466 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005467 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005468 }
5469
5470 return (RegNo == (unsigned)-1);
5471 }
5472
5473 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005474 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005475}
5476
Jack Carterb5cf5902013-04-17 00:18:04 +00005477bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005478 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005479
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005480 if (isParenExpr)
5481 return getParser().parseParenExprOfDepth(0, Res, S);
5482 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005483}
5484
Alex Bradbury58eba092016-11-01 16:32:05 +00005485OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005486MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005487 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005488 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005489 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005490 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005491 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005492 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005493 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005494 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005495
Jack Carterb5cf5902013-04-17 00:18:04 +00005496 if (getLexer().getKind() == AsmToken::LParen) {
5497 Parser.Lex();
5498 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005499 }
5500
Jack Carterb5cf5902013-04-17 00:18:04 +00005501 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005502 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005503 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005504
Jack Carterd0bd6422013-04-18 00:41:53 +00005505 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005506 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005507 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005508 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005509 SMLoc E =
5510 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005511 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005512 return MatchOperand_Success;
5513 }
5514 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005515 SMLoc E =
5516 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005517
Jack Carterd0bd6422013-04-18 00:41:53 +00005518 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005519 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005520 auto Base = MipsOperand::createGPRReg(
5521 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005522 Operands.push_back(
5523 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005524 return MatchOperand_Success;
5525 }
Simon Dardis858915f2016-10-18 15:17:17 +00005526 MCBinaryExpr::Opcode Opcode;
5527 // GAS and LLVM treat comparison operators different. GAS will generate -1
5528 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5529 // highly unlikely to be found in a memory offset expression, we don't
5530 // handle them.
5531 switch (Tok.getKind()) {
5532 case AsmToken::Plus:
5533 Opcode = MCBinaryExpr::Add;
5534 Parser.Lex();
5535 break;
5536 case AsmToken::Minus:
5537 Opcode = MCBinaryExpr::Sub;
5538 Parser.Lex();
5539 break;
5540 case AsmToken::Star:
5541 Opcode = MCBinaryExpr::Mul;
5542 Parser.Lex();
5543 break;
5544 case AsmToken::Pipe:
5545 Opcode = MCBinaryExpr::Or;
5546 Parser.Lex();
5547 break;
5548 case AsmToken::Amp:
5549 Opcode = MCBinaryExpr::And;
5550 Parser.Lex();
5551 break;
5552 case AsmToken::LessLess:
5553 Opcode = MCBinaryExpr::Shl;
5554 Parser.Lex();
5555 break;
5556 case AsmToken::GreaterGreater:
5557 Opcode = MCBinaryExpr::LShr;
5558 Parser.Lex();
5559 break;
5560 case AsmToken::Caret:
5561 Opcode = MCBinaryExpr::Xor;
5562 Parser.Lex();
5563 break;
5564 case AsmToken::Slash:
5565 Opcode = MCBinaryExpr::Div;
5566 Parser.Lex();
5567 break;
5568 case AsmToken::Percent:
5569 Opcode = MCBinaryExpr::Mod;
5570 Parser.Lex();
5571 break;
5572 default:
5573 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5574 return MatchOperand_ParseFail;
5575 }
5576 const MCExpr * NextExpr;
5577 if (getParser().parseExpression(NextExpr))
5578 return MatchOperand_ParseFail;
5579 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005580 }
5581
Jack Carterd0bd6422013-04-18 00:41:53 +00005582 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005583 }
5584
Toma Tabacu13964452014-09-04 13:23:44 +00005585 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005586 if (Res != MatchOperand_Success)
5587 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005588
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005589 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005590 Error(Parser.getTok().getLoc(), "')' expected");
5591 return MatchOperand_ParseFail;
5592 }
5593
Jack Carter873c7242013-01-12 01:03:14 +00005594 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5595
Jack Carterd0bd6422013-04-18 00:41:53 +00005596 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005597
Craig Topper062a2ba2014-04-25 05:30:21 +00005598 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005599 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005600
Jack Carterd0bd6422013-04-18 00:41:53 +00005601 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005602 std::unique_ptr<MipsOperand> op(
5603 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005604 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005605 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005606 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005607 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005608 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5609 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005610 if (IdVal->evaluateAsAbsolute(Imm))
5611 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005612 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005613 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005614 getContext());
5615 }
5616
David Blaikie960ea3f2014-06-08 16:18:35 +00005617 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005618 return MatchOperand_Success;
5619}
5620
David Blaikie960ea3f2014-06-08 16:18:35 +00005621bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005622 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005623 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005624 if (Sym) {
5625 SMLoc S = Parser.getTok().getLoc();
5626 const MCExpr *Expr;
5627 if (Sym->isVariable())
5628 Expr = Sym->getVariableValue();
5629 else
5630 return false;
5631 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005632 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005633 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005634 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005635 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005636 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005637 if (ResTy == MatchOperand_Success) {
5638 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005639 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005640 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005641 llvm_unreachable("Should never ParseFail");
5642 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005643 }
Jack Carterd76b2372013-03-21 21:44:16 +00005644 }
5645 }
5646 return false;
5647}
Jack Carterd0bd6422013-04-18 00:41:53 +00005648
Alex Bradbury58eba092016-11-01 16:32:05 +00005649OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005650MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005651 StringRef Identifier,
5652 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005653 int Index = matchCPURegisterName(Identifier);
5654 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005655 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005656 Index, Identifier, getContext().getRegisterInfo(), S,
5657 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005658 return MatchOperand_Success;
5659 }
5660
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005661 Index = matchHWRegsRegisterName(Identifier);
5662 if (Index != -1) {
5663 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005664 Index, Identifier, getContext().getRegisterInfo(), S,
5665 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005666 return MatchOperand_Success;
5667 }
5668
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005669 Index = matchFPURegisterName(Identifier);
5670 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005671 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005672 Index, Identifier, getContext().getRegisterInfo(), S,
5673 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005674 return MatchOperand_Success;
5675 }
5676
5677 Index = matchFCCRegisterName(Identifier);
5678 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005679 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005680 Index, Identifier, getContext().getRegisterInfo(), S,
5681 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005682 return MatchOperand_Success;
5683 }
5684
5685 Index = matchACRegisterName(Identifier);
5686 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005687 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005688 Index, Identifier, getContext().getRegisterInfo(), S,
5689 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005690 return MatchOperand_Success;
5691 }
5692
5693 Index = matchMSA128RegisterName(Identifier);
5694 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005695 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005696 Index, Identifier, getContext().getRegisterInfo(), S,
5697 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005698 return MatchOperand_Success;
5699 }
5700
5701 Index = matchMSA128CtrlRegisterName(Identifier);
5702 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005703 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005704 Index, Identifier, getContext().getRegisterInfo(), S,
5705 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005706 return MatchOperand_Success;
5707 }
5708
5709 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00005710}
5711
Alex Bradbury58eba092016-11-01 16:32:05 +00005712OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005713MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005714 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00005715 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005716
5717 if (Token.is(AsmToken::Identifier)) {
5718 DEBUG(dbgs() << ".. identifier\n");
5719 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00005720 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005721 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00005722 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005723 } else if (Token.is(AsmToken::Integer)) {
5724 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00005725 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005726 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
5727 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005728 return MatchOperand_Success;
5729 }
5730
5731 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
5732
5733 return MatchOperand_NoMatch;
5734}
5735
Alex Bradbury58eba092016-11-01 16:32:05 +00005736OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005737MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005738 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005739 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005740
5741 auto Token = Parser.getTok();
5742
5743 SMLoc S = Token.getLoc();
5744
5745 if (Token.isNot(AsmToken::Dollar)) {
5746 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
5747 if (Token.is(AsmToken::Identifier)) {
5748 if (searchSymbolAlias(Operands))
5749 return MatchOperand_Success;
5750 }
5751 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
5752 return MatchOperand_NoMatch;
5753 }
5754 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005755
Toma Tabacu13964452014-09-04 13:23:44 +00005756 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00005757 if (ResTy == MatchOperand_Success) {
5758 Parser.Lex(); // $
5759 Parser.Lex(); // identifier
5760 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005761 return ResTy;
5762}
5763
Alex Bradbury58eba092016-11-01 16:32:05 +00005764OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005765MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005766 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005767 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005768
5769 SMLoc S = getLexer().getLoc();
5770
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005771 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005772 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00005773 if (ResTy != MatchOperand_NoMatch)
5774 return ResTy;
5775
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005776 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00005777 const MCExpr *Expr = nullptr;
5778 if (Parser.parseExpression(Expr)) {
5779 // We have no way of knowing if a symbol was consumed so we must ParseFail
5780 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005781 }
Daniel Sandersffd84362014-04-01 10:41:48 +00005782 Operands.push_back(
5783 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005784 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00005785}
5786
Alex Bradbury58eba092016-11-01 16:32:05 +00005787OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005788MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005789 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00005790 const MCExpr *IdVal;
5791 // If the first token is '$' we may have register operand.
5792 if (Parser.getTok().is(AsmToken::Dollar))
5793 return MatchOperand_NoMatch;
5794 SMLoc S = Parser.getTok().getLoc();
5795 if (getParser().parseExpression(IdVal))
5796 return MatchOperand_ParseFail;
5797 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00005798 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00005799 int64_t Val = MCE->getValue();
5800 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5801 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00005802 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00005803 return MatchOperand_Success;
5804}
5805
Alex Bradbury58eba092016-11-01 16:32:05 +00005806OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005807MipsAsmParser::parseRegisterList(OperandVector &Operands) {
5808 MCAsmParser &Parser = getParser();
5809 SmallVector<unsigned, 10> Regs;
5810 unsigned RegNo;
5811 unsigned PrevReg = Mips::NoRegister;
5812 bool RegRange = false;
5813 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5814
5815 if (Parser.getTok().isNot(AsmToken::Dollar))
5816 return MatchOperand_ParseFail;
5817
5818 SMLoc S = Parser.getTok().getLoc();
5819 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
5820 SMLoc E = getLexer().getLoc();
5821 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
5822 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
5823 if (RegRange) {
5824 // Remove last register operand because registers from register range
5825 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005826 if ((isGP64bit() && RegNo == Mips::RA_64) ||
5827 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005828 Regs.push_back(RegNo);
5829 } else {
5830 unsigned TmpReg = PrevReg + 1;
5831 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005832 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
5833 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
5834 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005835 Error(E, "invalid register operand");
5836 return MatchOperand_ParseFail;
5837 }
5838
5839 PrevReg = TmpReg;
5840 Regs.push_back(TmpReg++);
5841 }
5842 }
5843
5844 RegRange = false;
5845 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005846 if ((PrevReg == Mips::NoRegister) &&
5847 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5848 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005849 Error(E, "$16 or $31 expected");
5850 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005851 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5852 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5853 !isGP64bit()) ||
5854 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5855 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5856 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005857 Error(E, "invalid register operand");
5858 return MatchOperand_ParseFail;
5859 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005860 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5861 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5862 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005863 Error(E, "consecutive register numbers expected");
5864 return MatchOperand_ParseFail;
5865 }
5866
5867 Regs.push_back(RegNo);
5868 }
5869
5870 if (Parser.getTok().is(AsmToken::Minus))
5871 RegRange = true;
5872
5873 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5874 !Parser.getTok().isNot(AsmToken::Comma)) {
5875 Error(E, "',' or '-' expected");
5876 return MatchOperand_ParseFail;
5877 }
5878
5879 Lex(); // Consume comma or minus
5880 if (Parser.getTok().isNot(AsmToken::Dollar))
5881 break;
5882
5883 PrevReg = RegNo;
5884 }
5885
5886 SMLoc E = Parser.getTok().getLoc();
5887 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5888 parseMemOperand(Operands);
5889 return MatchOperand_Success;
5890}
5891
Alex Bradbury58eba092016-11-01 16:32:05 +00005892OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005893MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5894 MCAsmParser &Parser = getParser();
5895
5896 SMLoc S = Parser.getTok().getLoc();
5897 if (parseAnyRegister(Operands) != MatchOperand_Success)
5898 return MatchOperand_ParseFail;
5899
5900 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005901 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005902
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005903 Operands.pop_back();
5904 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005905 return MatchOperand_Success;
5906}
5907
Alex Bradbury58eba092016-11-01 16:32:05 +00005908OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005909MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5910 MCAsmParser &Parser = getParser();
5911 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5912 SmallVector<unsigned, 10> Regs;
5913
5914 if (Parser.getTok().isNot(AsmToken::Dollar))
5915 return MatchOperand_ParseFail;
5916
5917 SMLoc S = Parser.getTok().getLoc();
5918
5919 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5920 return MatchOperand_ParseFail;
5921
5922 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5923 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5924 Regs.push_back(RegNo);
5925
5926 SMLoc E = Parser.getTok().getLoc();
5927 if (Parser.getTok().isNot(AsmToken::Comma)) {
5928 Error(E, "',' expected");
5929 return MatchOperand_ParseFail;
5930 }
5931
5932 // Remove comma.
5933 Parser.Lex();
5934
5935 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5936 return MatchOperand_ParseFail;
5937
5938 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5939 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5940 Regs.push_back(RegNo);
5941
5942 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5943
5944 return MatchOperand_Success;
5945}
5946
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005947/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5948/// either this.
5949/// ::= '(', register, ')'
5950/// handle it before we iterate so we don't get tripped up by the lack of
5951/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005952bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005953 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005954 if (getLexer().is(AsmToken::LParen)) {
5955 Operands.push_back(
5956 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5957 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005958 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005959 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005960 return Error(Loc, "unexpected token in argument list");
5961 }
5962 if (Parser.getTok().isNot(AsmToken::RParen)) {
5963 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005964 return Error(Loc, "unexpected token, expected ')'");
5965 }
5966 Operands.push_back(
5967 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5968 Parser.Lex();
5969 }
5970 return false;
5971}
5972
5973/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5974/// either one of these.
5975/// ::= '[', register, ']'
5976/// ::= '[', integer, ']'
5977/// handle it before we iterate so we don't get tripped up by the lack of
5978/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005979bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005980 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005981 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005982 if (getLexer().is(AsmToken::LBrac)) {
5983 Operands.push_back(
5984 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5985 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005986 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005987 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005988 return Error(Loc, "unexpected token in argument list");
5989 }
5990 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5991 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005992 return Error(Loc, "unexpected token, expected ']'");
5993 }
5994 Operands.push_back(
5995 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5996 Parser.Lex();
5997 }
5998 return false;
5999}
6000
David Blaikie960ea3f2014-06-08 16:18:35 +00006001bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6002 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006003 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006004 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006005
6006 // We have reached first instruction, module directive are now forbidden.
6007 getTargetStreamer().forbidModuleDirective();
6008
Vladimir Medic74593e62013-07-17 15:00:42 +00006009 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006010 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006011 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006012 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006013 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006014 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006015
6016 // Read the remaining operands.
6017 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6018 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006019 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006020 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006021 return Error(Loc, "unexpected token in argument list");
6022 }
Toma Tabacu13964452014-09-04 13:23:44 +00006023 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006024 return true;
6025 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006026
Jack Carterd0bd6422013-04-18 00:41:53 +00006027 while (getLexer().is(AsmToken::Comma)) {
6028 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006029 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006030 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006031 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006032 return Error(Loc, "unexpected token in argument list");
6033 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006034 // Parse bracket and parenthesis suffixes before we iterate
6035 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006036 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006037 return true;
6038 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006039 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006040 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006041 }
6042 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006043 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6044 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006045 return Error(Loc, "unexpected token in argument list");
6046 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006047 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006048 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006049}
6050
Nirav Dave996fc132016-05-05 14:15:46 +00006051// FIXME: Given that these have the same name, these should both be
6052// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006053bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006054 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006055 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006056}
6057
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006058bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006059 return Error(Loc, ErrorMsg);
6060}
6061
Jack Carter0b744b32012-10-04 02:29:46 +00006062bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006063 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006064 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006065
6066 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006067 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006068
6069 Parser.Lex(); // Eat "noat".
6070
Jack Carterd0bd6422013-04-18 00:41:53 +00006071 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006072 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006073 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006074 return false;
6075 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006076
6077 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006078 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006079 return false;
6080}
Jack Carterd0bd6422013-04-18 00:41:53 +00006081
Jack Carter0b744b32012-10-04 02:29:46 +00006082bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006083 // Line can be: ".set at", which sets $at to $1
6084 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006085 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006086 Parser.Lex(); // Eat "at".
6087
Jack Carter0b744b32012-10-04 02:29:46 +00006088 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006089 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006090 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006091
6092 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006093 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006094 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006095 }
6096
6097 if (getLexer().isNot(AsmToken::Equal)) {
6098 reportParseError("unexpected token, expected equals sign");
6099 return false;
6100 }
6101 Parser.Lex(); // Eat "=".
6102
6103 if (getLexer().isNot(AsmToken::Dollar)) {
6104 if (getLexer().is(AsmToken::EndOfStatement)) {
6105 reportParseError("no register specified");
6106 return false;
6107 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006108 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006109 return false;
6110 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006111 }
6112 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006113
Toma Tabacu16a74492015-02-13 10:30:57 +00006114 // Find out what "reg" is.
6115 unsigned AtRegNo;
6116 const AsmToken &Reg = Parser.getTok();
6117 if (Reg.is(AsmToken::Identifier)) {
6118 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6119 } else if (Reg.is(AsmToken::Integer)) {
6120 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006121 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006122 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006123 return false;
6124 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006125
6126 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006127 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006128 reportParseError("invalid register");
6129 return false;
6130 }
6131 Parser.Lex(); // Eat "reg".
6132
6133 // If this is not the end of the statement, report an error.
6134 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6135 reportParseError("unexpected token, expected end of statement");
6136 return false;
6137 }
6138
6139 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6140
6141 Parser.Lex(); // Consume the EndOfStatement.
6142 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006143}
6144
6145bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006146 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006147 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006148 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006149 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006150 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006151 return false;
6152 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006153 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006154 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006155 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006156 return false;
6157}
6158
6159bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006160 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006161 Parser.Lex();
6162 // If this is not the end of the statement, report an error.
6163 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006164 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006165 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006166 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006167 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006168 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006169 Parser.Lex(); // Consume the EndOfStatement.
6170 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006171}
6172
6173bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006174 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006175 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006176 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006177 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006178 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006179 return false;
6180 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006181 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006182 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006183 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006184 return false;
6185}
6186
6187bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006188 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006189 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006190 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006191 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006192 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006193 return false;
6194 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006195 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006196 reportParseError("`noreorder' must be set before `nomacro'");
6197 return false;
6198 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006199 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006200 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006201 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006202 return false;
6203}
Jack Carterd76b2372013-03-21 21:44:16 +00006204
Daniel Sanders44934432014-08-07 12:03:36 +00006205bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006206 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006207 Parser.Lex();
6208
6209 // If this is not the end of the statement, report an error.
6210 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006211 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006212
6213 setFeatureBits(Mips::FeatureMSA, "msa");
6214 getTargetStreamer().emitDirectiveSetMsa();
6215 return false;
6216}
6217
6218bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006219 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006220 Parser.Lex();
6221
6222 // If this is not the end of the statement, report an error.
6223 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006224 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006225
6226 clearFeatureBits(Mips::FeatureMSA, "msa");
6227 getTargetStreamer().emitDirectiveSetNoMsa();
6228 return false;
6229}
6230
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006231bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006232 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006233 Parser.Lex(); // Eat "nodsp".
6234
6235 // If this is not the end of the statement, report an error.
6236 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6237 reportParseError("unexpected token, expected end of statement");
6238 return false;
6239 }
6240
6241 clearFeatureBits(Mips::FeatureDSP, "dsp");
6242 getTargetStreamer().emitDirectiveSetNoDsp();
6243 return false;
6244}
6245
Toma Tabacucc2502d2014-11-04 17:18:07 +00006246bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006247 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006248 Parser.Lex(); // Eat "mips16".
6249
Jack Carter39536722014-01-22 23:08:42 +00006250 // If this is not the end of the statement, report an error.
6251 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006252 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006253 return false;
6254 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006255
6256 setFeatureBits(Mips::FeatureMips16, "mips16");
6257 getTargetStreamer().emitDirectiveSetMips16();
6258 Parser.Lex(); // Consume the EndOfStatement.
6259 return false;
6260}
6261
6262bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006263 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006264 Parser.Lex(); // Eat "nomips16".
6265
6266 // If this is not the end of the statement, report an error.
6267 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6268 reportParseError("unexpected token, expected end of statement");
6269 return false;
6270 }
6271
6272 clearFeatureBits(Mips::FeatureMips16, "mips16");
6273 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006274 Parser.Lex(); // Consume the EndOfStatement.
6275 return false;
6276}
6277
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006278bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006279 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006280 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006281 // Line can be: .set fp=32
6282 // .set fp=xx
6283 // .set fp=64
6284 Parser.Lex(); // Eat fp token
6285 AsmToken Tok = Parser.getTok();
6286 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006287 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006288 return false;
6289 }
6290 Parser.Lex(); // Eat '=' token.
6291 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006292
6293 if (!parseFpABIValue(FpAbiVal, ".set"))
6294 return false;
6295
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006296 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006297 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006298 return false;
6299 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006300 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006301 Parser.Lex(); // Consume the EndOfStatement.
6302 return false;
6303}
6304
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006305bool MipsAsmParser::parseSetOddSPRegDirective() {
6306 MCAsmParser &Parser = getParser();
6307
6308 Parser.Lex(); // Eat "oddspreg".
6309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6310 reportParseError("unexpected token, expected end of statement");
6311 return false;
6312 }
6313
6314 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6315 getTargetStreamer().emitDirectiveSetOddSPReg();
6316 return false;
6317}
6318
6319bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6320 MCAsmParser &Parser = getParser();
6321
6322 Parser.Lex(); // Eat "nooddspreg".
6323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6324 reportParseError("unexpected token, expected end of statement");
6325 return false;
6326 }
6327
6328 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6329 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6330 return false;
6331}
6332
Toma Tabacu9db22db2014-09-09 10:15:38 +00006333bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006334 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006335 SMLoc Loc = getLexer().getLoc();
6336
6337 Parser.Lex();
6338 if (getLexer().isNot(AsmToken::EndOfStatement))
6339 return reportParseError("unexpected token, expected end of statement");
6340
6341 // Always keep an element on the options "stack" to prevent the user
6342 // from changing the initial options. This is how we remember them.
6343 if (AssemblerOptions.size() == 2)
6344 return reportParseError(Loc, ".set pop with no .set push");
6345
Akira Hatanakab11ef082015-11-14 06:35:56 +00006346 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006347 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006348 setAvailableFeatures(
6349 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6350 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006351
6352 getTargetStreamer().emitDirectiveSetPop();
6353 return false;
6354}
6355
6356bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006357 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006358 Parser.Lex();
6359 if (getLexer().isNot(AsmToken::EndOfStatement))
6360 return reportParseError("unexpected token, expected end of statement");
6361
6362 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006363 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006364 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006365
6366 getTargetStreamer().emitDirectiveSetPush();
6367 return false;
6368}
6369
Toma Tabacu29696502015-06-02 09:48:04 +00006370bool MipsAsmParser::parseSetSoftFloatDirective() {
6371 MCAsmParser &Parser = getParser();
6372 Parser.Lex();
6373 if (getLexer().isNot(AsmToken::EndOfStatement))
6374 return reportParseError("unexpected token, expected end of statement");
6375
6376 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6377 getTargetStreamer().emitDirectiveSetSoftFloat();
6378 return false;
6379}
6380
6381bool MipsAsmParser::parseSetHardFloatDirective() {
6382 MCAsmParser &Parser = getParser();
6383 Parser.Lex();
6384 if (getLexer().isNot(AsmToken::EndOfStatement))
6385 return reportParseError("unexpected token, expected end of statement");
6386
6387 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6388 getTargetStreamer().emitDirectiveSetHardFloat();
6389 return false;
6390}
6391
Jack Carterd76b2372013-03-21 21:44:16 +00006392bool MipsAsmParser::parseSetAssignment() {
6393 StringRef Name;
6394 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006395 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006396
6397 if (Parser.parseIdentifier(Name))
6398 reportParseError("expected identifier after .set");
6399
6400 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006401 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006402 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006403
Jack Carter3b2c96e2014-01-22 23:31:38 +00006404 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006405 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006406
Jim Grosbach6f482002015-05-18 18:43:14 +00006407 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006408 Sym->setVariableValue(Value);
6409
6410 return false;
6411}
Jack Carterd0bd6422013-04-18 00:41:53 +00006412
Toma Tabacu26647792014-09-09 12:52:14 +00006413bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006414 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006415 Parser.Lex();
6416 if (getLexer().isNot(AsmToken::EndOfStatement))
6417 return reportParseError("unexpected token, expected end of statement");
6418
6419 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006420 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006421 setAvailableFeatures(
6422 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6423 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006424 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6425
6426 getTargetStreamer().emitDirectiveSetMips0();
6427 return false;
6428}
6429
Toma Tabacu85618b32014-08-19 14:22:52 +00006430bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006431 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006432 Parser.Lex();
6433 if (getLexer().isNot(AsmToken::Equal))
6434 return reportParseError("unexpected token, expected equals sign");
6435
6436 Parser.Lex();
6437 StringRef Arch;
6438 if (Parser.parseIdentifier(Arch))
6439 return reportParseError("expected arch identifier");
6440
6441 StringRef ArchFeatureName =
6442 StringSwitch<StringRef>(Arch)
6443 .Case("mips1", "mips1")
6444 .Case("mips2", "mips2")
6445 .Case("mips3", "mips3")
6446 .Case("mips4", "mips4")
6447 .Case("mips5", "mips5")
6448 .Case("mips32", "mips32")
6449 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006450 .Case("mips32r3", "mips32r3")
6451 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006452 .Case("mips32r6", "mips32r6")
6453 .Case("mips64", "mips64")
6454 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006455 .Case("mips64r3", "mips64r3")
6456 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006457 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006458 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006459 .Case("r4000", "mips3") // This is an implementation of Mips3.
6460 .Default("");
6461
6462 if (ArchFeatureName.empty())
6463 return reportParseError("unsupported architecture");
6464
6465 selectArch(ArchFeatureName);
6466 getTargetStreamer().emitDirectiveSetArch(Arch);
6467 return false;
6468}
6469
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006470bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006471 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006472 Parser.Lex();
6473 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006474 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006475
Matheus Almeida2852af82014-04-22 10:15:54 +00006476 switch (Feature) {
6477 default:
6478 llvm_unreachable("Unimplemented feature");
6479 case Mips::FeatureDSP:
6480 setFeatureBits(Mips::FeatureDSP, "dsp");
6481 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006482 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006483 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006484 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006485 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006486 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006487 case Mips::FeatureMips1:
6488 selectArch("mips1");
6489 getTargetStreamer().emitDirectiveSetMips1();
6490 break;
6491 case Mips::FeatureMips2:
6492 selectArch("mips2");
6493 getTargetStreamer().emitDirectiveSetMips2();
6494 break;
6495 case Mips::FeatureMips3:
6496 selectArch("mips3");
6497 getTargetStreamer().emitDirectiveSetMips3();
6498 break;
6499 case Mips::FeatureMips4:
6500 selectArch("mips4");
6501 getTargetStreamer().emitDirectiveSetMips4();
6502 break;
6503 case Mips::FeatureMips5:
6504 selectArch("mips5");
6505 getTargetStreamer().emitDirectiveSetMips5();
6506 break;
6507 case Mips::FeatureMips32:
6508 selectArch("mips32");
6509 getTargetStreamer().emitDirectiveSetMips32();
6510 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006511 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006512 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006513 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006514 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006515 case Mips::FeatureMips32r3:
6516 selectArch("mips32r3");
6517 getTargetStreamer().emitDirectiveSetMips32R3();
6518 break;
6519 case Mips::FeatureMips32r5:
6520 selectArch("mips32r5");
6521 getTargetStreamer().emitDirectiveSetMips32R5();
6522 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006523 case Mips::FeatureMips32r6:
6524 selectArch("mips32r6");
6525 getTargetStreamer().emitDirectiveSetMips32R6();
6526 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006527 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006528 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006529 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006530 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006531 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006532 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006533 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006534 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006535 case Mips::FeatureMips64r3:
6536 selectArch("mips64r3");
6537 getTargetStreamer().emitDirectiveSetMips64R3();
6538 break;
6539 case Mips::FeatureMips64r5:
6540 selectArch("mips64r5");
6541 getTargetStreamer().emitDirectiveSetMips64R5();
6542 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006543 case Mips::FeatureMips64r6:
6544 selectArch("mips64r6");
6545 getTargetStreamer().emitDirectiveSetMips64R6();
6546 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006547 }
6548 return false;
6549}
6550
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006551bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006552 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006553 if (getLexer().isNot(AsmToken::Comma)) {
6554 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006555 return Error(Loc, ErrorStr);
6556 }
6557
Matheus Almeida2852af82014-04-22 10:15:54 +00006558 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006559 return true;
6560}
6561
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006562// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6563// In this class, it is only used for .cprestore.
6564// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6565// MipsTargetELFStreamer and MipsAsmParser.
6566bool MipsAsmParser::isPicAndNotNxxAbi() {
6567 return inPicMode() && !(isABI_N32() || isABI_N64());
6568}
6569
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006570bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006571 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006572 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006573
Toma Tabacudde4c462014-11-06 10:02:45 +00006574 if (inMips16Mode()) {
6575 reportParseError(".cpload is not supported in Mips16 mode");
6576 return false;
6577 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006578
David Blaikie960ea3f2014-06-08 16:18:35 +00006579 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006580 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006581 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6582 reportParseError("expected register containing function address");
6583 return false;
6584 }
6585
David Blaikie960ea3f2014-06-08 16:18:35 +00006586 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6587 if (!RegOpnd.isGPRAsmReg()) {
6588 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006589 return false;
6590 }
6591
Toma Tabacudde4c462014-11-06 10:02:45 +00006592 // If this is not the end of the statement, report an error.
6593 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6594 reportParseError("unexpected token, expected end of statement");
6595 return false;
6596 }
6597
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006598 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006599 return false;
6600}
6601
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006602bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6603 MCAsmParser &Parser = getParser();
6604
6605 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6606 // is used in non-PIC mode.
6607
6608 if (inMips16Mode()) {
6609 reportParseError(".cprestore is not supported in Mips16 mode");
6610 return false;
6611 }
6612
6613 // Get the stack offset value.
6614 const MCExpr *StackOffset;
6615 int64_t StackOffsetVal;
6616 if (Parser.parseExpression(StackOffset)) {
6617 reportParseError("expected stack offset value");
6618 return false;
6619 }
6620
6621 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6622 reportParseError("stack offset is not an absolute expression");
6623 return false;
6624 }
6625
6626 if (StackOffsetVal < 0) {
6627 Warning(Loc, ".cprestore with negative stack offset has no effect");
6628 IsCpRestoreSet = false;
6629 } else {
6630 IsCpRestoreSet = true;
6631 CpRestoreOffset = StackOffsetVal;
6632 }
6633
6634 // If this is not the end of the statement, report an error.
6635 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6636 reportParseError("unexpected token, expected end of statement");
6637 return false;
6638 }
6639
Daniel Sandersdf8510d2016-05-11 12:48:19 +00006640 if (!getTargetStreamer().emitDirectiveCpRestore(
6641 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00006642 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006643 Parser.Lex(); // Consume the EndOfStatement.
6644 return false;
6645}
6646
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006647bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006648 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006649 unsigned FuncReg;
6650 unsigned Save;
6651 bool SaveIsReg = true;
6652
Matheus Almeida7e815762014-06-18 13:08:59 +00006653 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006654 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006655 if (ResTy == MatchOperand_NoMatch) {
6656 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00006657 return false;
6658 }
6659
6660 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6661 if (!FuncRegOpnd.isGPRAsmReg()) {
6662 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006663 return false;
6664 }
6665
6666 FuncReg = FuncRegOpnd.getGPR32Reg();
6667 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006668
Toma Tabacu65f10572014-09-16 15:00:52 +00006669 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006670 return true;
6671
Toma Tabacu13964452014-09-04 13:23:44 +00006672 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00006673 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00006674 const MCExpr *OffsetExpr;
6675 int64_t OffsetVal;
6676 SMLoc ExprLoc = getLexer().getLoc();
6677
6678 if (Parser.parseExpression(OffsetExpr) ||
6679 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
6680 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00006681 return false;
6682 }
Daniel Sanders5d796282015-09-21 09:26:55 +00006683
6684 Save = OffsetVal;
6685 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00006686 } else {
6687 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6688 if (!SaveOpnd.isGPRAsmReg()) {
6689 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00006690 return false;
6691 }
6692 Save = SaveOpnd.getGPR32Reg();
6693 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006694
Toma Tabacu65f10572014-09-16 15:00:52 +00006695 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006696 return true;
6697
Toma Tabacu8874eac2015-02-18 13:46:53 +00006698 const MCExpr *Expr;
6699 if (Parser.parseExpression(Expr)) {
6700 reportParseError("expected expression");
6701 return false;
6702 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006703
Toma Tabacu8874eac2015-02-18 13:46:53 +00006704 if (Expr->getKind() != MCExpr::SymbolRef) {
6705 reportParseError("expected symbol");
6706 return false;
6707 }
6708 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
6709
Daniel Sandersf173dda2015-09-22 10:50:09 +00006710 CpSaveLocation = Save;
6711 CpSaveLocationIsRegister = SaveIsReg;
6712
Toma Tabacu8874eac2015-02-18 13:46:53 +00006713 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
6714 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006715 return false;
6716}
6717
Daniel Sandersf173dda2015-09-22 10:50:09 +00006718bool MipsAsmParser::parseDirectiveCPReturn() {
6719 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
6720 CpSaveLocationIsRegister);
6721 return false;
6722}
6723
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006724bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006725 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006726 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6727 const AsmToken &Tok = Parser.getTok();
6728
6729 if (Tok.getString() == "2008") {
6730 Parser.Lex();
6731 getTargetStreamer().emitDirectiveNaN2008();
6732 return false;
6733 } else if (Tok.getString() == "legacy") {
6734 Parser.Lex();
6735 getTargetStreamer().emitDirectiveNaNLegacy();
6736 return false;
6737 }
6738 }
6739 // If we don't recognize the option passed to the .nan
6740 // directive (e.g. no option or unknown option), emit an error.
6741 reportParseError("invalid option in .nan directive");
6742 return false;
6743}
6744
Jack Carter0b744b32012-10-04 02:29:46 +00006745bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006746 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006747 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00006748 const AsmToken &Tok = Parser.getTok();
6749
6750 if (Tok.getString() == "noat") {
6751 return parseSetNoAtDirective();
6752 } else if (Tok.getString() == "at") {
6753 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00006754 } else if (Tok.getString() == "arch") {
6755 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00006756 } else if (Tok.getString() == "bopt") {
6757 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
6758 getParser().Lex();
6759 return false;
6760 } else if (Tok.getString() == "nobopt") {
6761 // We're already running in nobopt mode, so nothing to do.
6762 getParser().Lex();
6763 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006764 } else if (Tok.getString() == "fp") {
6765 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006766 } else if (Tok.getString() == "oddspreg") {
6767 return parseSetOddSPRegDirective();
6768 } else if (Tok.getString() == "nooddspreg") {
6769 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006770 } else if (Tok.getString() == "pop") {
6771 return parseSetPopDirective();
6772 } else if (Tok.getString() == "push") {
6773 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00006774 } else if (Tok.getString() == "reorder") {
6775 return parseSetReorderDirective();
6776 } else if (Tok.getString() == "noreorder") {
6777 return parseSetNoReorderDirective();
6778 } else if (Tok.getString() == "macro") {
6779 return parseSetMacroDirective();
6780 } else if (Tok.getString() == "nomacro") {
6781 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00006782 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00006783 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006784 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00006785 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00006786 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00006787 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00006788 getTargetStreamer().emitDirectiveSetNoMicroMips();
6789 Parser.eatToEndOfStatement();
6790 return false;
6791 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006792 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00006793 } else if (Tok.getString() == "mips0") {
6794 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00006795 } else if (Tok.getString() == "mips1") {
6796 return parseSetFeature(Mips::FeatureMips1);
6797 } else if (Tok.getString() == "mips2") {
6798 return parseSetFeature(Mips::FeatureMips2);
6799 } else if (Tok.getString() == "mips3") {
6800 return parseSetFeature(Mips::FeatureMips3);
6801 } else if (Tok.getString() == "mips4") {
6802 return parseSetFeature(Mips::FeatureMips4);
6803 } else if (Tok.getString() == "mips5") {
6804 return parseSetFeature(Mips::FeatureMips5);
6805 } else if (Tok.getString() == "mips32") {
6806 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00006807 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006808 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006809 } else if (Tok.getString() == "mips32r3") {
6810 return parseSetFeature(Mips::FeatureMips32r3);
6811 } else if (Tok.getString() == "mips32r5") {
6812 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006813 } else if (Tok.getString() == "mips32r6") {
6814 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006815 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006816 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006817 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006818 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00006819 } else if (Tok.getString() == "mips64r3") {
6820 return parseSetFeature(Mips::FeatureMips64r3);
6821 } else if (Tok.getString() == "mips64r5") {
6822 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00006823 } else if (Tok.getString() == "mips64r6") {
6824 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00006825 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00006826 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006827 } else if (Tok.getString() == "nodsp") {
6828 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00006829 } else if (Tok.getString() == "msa") {
6830 return parseSetMsaDirective();
6831 } else if (Tok.getString() == "nomsa") {
6832 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00006833 } else if (Tok.getString() == "softfloat") {
6834 return parseSetSoftFloatDirective();
6835 } else if (Tok.getString() == "hardfloat") {
6836 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00006837 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00006838 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00006839 parseSetAssignment();
6840 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006841 }
Jack Carter07c818d2013-01-25 01:31:34 +00006842
Jack Carter0b744b32012-10-04 02:29:46 +00006843 return true;
6844}
6845
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006846/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006847/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006848bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006849 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006851 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00006852 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006853 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006854 return true;
6855
6856 getParser().getStreamer().EmitValue(Value, Size);
6857
6858 if (getLexer().is(AsmToken::EndOfStatement))
6859 break;
6860
Jack Carter07c818d2013-01-25 01:31:34 +00006861 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006862 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006863 Parser.Lex();
6864 }
6865 }
6866
6867 Parser.Lex();
6868 return false;
6869}
6870
Vladimir Medic4c299852013-11-06 11:27:05 +00006871/// parseDirectiveGpWord
6872/// ::= .gpword local_sym
6873bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006874 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006875 const MCExpr *Value;
6876 // EmitGPRel32Value requires an expression, so we are using base class
6877 // method to evaluate the expression.
6878 if (getParser().parseExpression(Value))
6879 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006880 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006881
Vladimir Medice10c1122013-11-13 13:18:04 +00006882 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006883 return Error(getLexer().getLoc(),
6884 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006885 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006886 return false;
6887}
6888
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006889/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006890/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006891bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006892 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006893 const MCExpr *Value;
6894 // EmitGPRel64Value requires an expression, so we are using base class
6895 // method to evaluate the expression.
6896 if (getParser().parseExpression(Value))
6897 return true;
6898 getParser().getStreamer().EmitGPRel64Value(Value);
6899
6900 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006901 return Error(getLexer().getLoc(),
6902 "unexpected token, expected end of statement");
6903 Parser.Lex(); // Eat EndOfStatement token.
6904 return false;
6905}
6906
6907/// parseDirectiveDtpRelWord
6908/// ::= .dtprelword tls_sym
6909bool MipsAsmParser::parseDirectiveDtpRelWord() {
6910 MCAsmParser &Parser = getParser();
6911 const MCExpr *Value;
6912 // EmitDTPRel32Value requires an expression, so we are using base class
6913 // method to evaluate the expression.
6914 if (getParser().parseExpression(Value))
6915 return true;
6916 getParser().getStreamer().EmitDTPRel32Value(Value);
6917
6918 if (getLexer().isNot(AsmToken::EndOfStatement))
6919 return Error(getLexer().getLoc(),
6920 "unexpected token, expected end of statement");
6921 Parser.Lex(); // Eat EndOfStatement token.
6922 return false;
6923}
6924
6925/// parseDirectiveDtpRelDWord
6926/// ::= .dtpreldword tls_sym
6927bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6928 MCAsmParser &Parser = getParser();
6929 const MCExpr *Value;
6930 // EmitDTPRel64Value requires an expression, so we are using base class
6931 // method to evaluate the expression.
6932 if (getParser().parseExpression(Value))
6933 return true;
6934 getParser().getStreamer().EmitDTPRel64Value(Value);
6935
6936 if (getLexer().isNot(AsmToken::EndOfStatement))
6937 return Error(getLexer().getLoc(),
6938 "unexpected token, expected end of statement");
6939 Parser.Lex(); // Eat EndOfStatement token.
6940 return false;
6941}
6942
6943/// parseDirectiveTpRelWord
6944/// ::= .tprelword tls_sym
6945bool MipsAsmParser::parseDirectiveTpRelWord() {
6946 MCAsmParser &Parser = getParser();
6947 const MCExpr *Value;
6948 // EmitTPRel32Value requires an expression, so we are using base class
6949 // method to evaluate the expression.
6950 if (getParser().parseExpression(Value))
6951 return true;
6952 getParser().getStreamer().EmitTPRel32Value(Value);
6953
6954 if (getLexer().isNot(AsmToken::EndOfStatement))
6955 return Error(getLexer().getLoc(),
6956 "unexpected token, expected end of statement");
6957 Parser.Lex(); // Eat EndOfStatement token.
6958 return false;
6959}
6960
6961/// parseDirectiveTpRelDWord
6962/// ::= .tpreldword tls_sym
6963bool MipsAsmParser::parseDirectiveTpRelDWord() {
6964 MCAsmParser &Parser = getParser();
6965 const MCExpr *Value;
6966 // EmitTPRel64Value requires an expression, so we are using base class
6967 // method to evaluate the expression.
6968 if (getParser().parseExpression(Value))
6969 return true;
6970 getParser().getStreamer().EmitTPRel64Value(Value);
6971
6972 if (getLexer().isNot(AsmToken::EndOfStatement))
6973 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006974 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006975 Parser.Lex(); // Eat EndOfStatement token.
6976 return false;
6977}
6978
Jack Carter0cd3c192014-01-06 23:27:31 +00006979bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006980 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006981 // Get the option token.
6982 AsmToken Tok = Parser.getTok();
6983 // At the moment only identifiers are supported.
6984 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006985 return Error(Parser.getTok().getLoc(),
6986 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006987 }
6988
6989 StringRef Option = Tok.getIdentifier();
6990
6991 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006992 // MipsAsmParser needs to know if the current PIC mode changes.
6993 IsPicEnabled = false;
6994
Jack Carter0cd3c192014-01-06 23:27:31 +00006995 getTargetStreamer().emitDirectiveOptionPic0();
6996 Parser.Lex();
6997 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006998 return Error(Parser.getTok().getLoc(),
6999 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007000 }
7001 return false;
7002 }
7003
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007004 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007005 // MipsAsmParser needs to know if the current PIC mode changes.
7006 IsPicEnabled = true;
7007
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007008 getTargetStreamer().emitDirectiveOptionPic2();
7009 Parser.Lex();
7010 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007011 return Error(Parser.getTok().getLoc(),
7012 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007013 }
7014 return false;
7015 }
7016
Jack Carter0cd3c192014-01-06 23:27:31 +00007017 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007018 Warning(Parser.getTok().getLoc(),
7019 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007020 Parser.eatToEndOfStatement();
7021 return false;
7022}
7023
Toma Tabacu9ca50962015-04-16 09:53:47 +00007024/// parseInsnDirective
7025/// ::= .insn
7026bool MipsAsmParser::parseInsnDirective() {
7027 // If this is not the end of the statement, report an error.
7028 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7029 reportParseError("unexpected token, expected end of statement");
7030 return false;
7031 }
7032
7033 // The actual label marking happens in
7034 // MipsELFStreamer::createPendingLabelRelocs().
7035 getTargetStreamer().emitDirectiveInsn();
7036
7037 getParser().Lex(); // Eat EndOfStatement token.
7038 return false;
7039}
7040
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007041/// parseRSectionDirective
7042/// ::= .rdata
7043bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7044 // If this is not the end of the statement, report an error.
7045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7046 reportParseError("unexpected token, expected end of statement");
7047 return false;
7048 }
7049
7050 MCSection *ELFSection = getContext().getELFSection(
7051 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7052 getParser().getStreamer().SwitchSection(ELFSection);
7053
7054 getParser().Lex(); // Eat EndOfStatement token.
7055 return false;
7056}
7057
Simon Atanasyanbe186202016-02-11 06:45:54 +00007058/// parseSSectionDirective
7059/// ::= .sbss
7060/// ::= .sdata
7061bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7062 // If this is not the end of the statement, report an error.
7063 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7064 reportParseError("unexpected token, expected end of statement");
7065 return false;
7066 }
7067
7068 MCSection *ELFSection = getContext().getELFSection(
7069 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7070 getParser().getStreamer().SwitchSection(ELFSection);
7071
7072 getParser().Lex(); // Eat EndOfStatement token.
7073 return false;
7074}
7075
Daniel Sanders7e527422014-07-10 13:38:23 +00007076/// parseDirectiveModule
7077/// ::= .module oddspreg
7078/// ::= .module nooddspreg
7079/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007080/// ::= .module softfloat
7081/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007082bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007083 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007084 MCAsmLexer &Lexer = getLexer();
7085 SMLoc L = Lexer.getLoc();
7086
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007087 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007088 // TODO : get a better message.
7089 reportParseError(".module directive must appear before any code");
7090 return false;
7091 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007092
Toma Tabacuc405c822015-01-23 10:40:19 +00007093 StringRef Option;
7094 if (Parser.parseIdentifier(Option)) {
7095 reportParseError("expected .module option identifier");
7096 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007097 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007098
Toma Tabacuc405c822015-01-23 10:40:19 +00007099 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007100 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007101
Toma Tabacu3c499582015-06-25 10:56:57 +00007102 // Synchronize the abiflags information with the FeatureBits information we
7103 // changed above.
7104 getTargetStreamer().updateABIInfo(*this);
7105
7106 // If printing assembly, use the recently updated abiflags information.
7107 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7108 // emitted at the end).
7109 getTargetStreamer().emitDirectiveModuleOddSPReg();
7110
Toma Tabacuc405c822015-01-23 10:40:19 +00007111 // If this is not the end of the statement, report an error.
7112 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7113 reportParseError("unexpected token, expected end of statement");
7114 return false;
7115 }
7116
7117 return false; // parseDirectiveModule has finished successfully.
7118 } else if (Option == "nooddspreg") {
7119 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007120 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007121 }
7122
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007123 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007124
Toma Tabacu3c499582015-06-25 10:56:57 +00007125 // Synchronize the abiflags information with the FeatureBits information we
7126 // changed above.
7127 getTargetStreamer().updateABIInfo(*this);
7128
7129 // If printing assembly, use the recently updated abiflags information.
7130 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7131 // emitted at the end).
7132 getTargetStreamer().emitDirectiveModuleOddSPReg();
7133
Toma Tabacuc405c822015-01-23 10:40:19 +00007134 // If this is not the end of the statement, report an error.
7135 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7136 reportParseError("unexpected token, expected end of statement");
7137 return false;
7138 }
7139
7140 return false; // parseDirectiveModule has finished successfully.
7141 } else if (Option == "fp") {
7142 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007143 } else if (Option == "softfloat") {
7144 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7145
7146 // Synchronize the ABI Flags information with the FeatureBits information we
7147 // updated above.
7148 getTargetStreamer().updateABIInfo(*this);
7149
7150 // If printing assembly, use the recently updated ABI Flags information.
7151 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7152 // emitted later).
7153 getTargetStreamer().emitDirectiveModuleSoftFloat();
7154
7155 // If this is not the end of the statement, report an error.
7156 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7157 reportParseError("unexpected token, expected end of statement");
7158 return false;
7159 }
7160
7161 return false; // parseDirectiveModule has finished successfully.
7162 } else if (Option == "hardfloat") {
7163 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7164
7165 // Synchronize the ABI Flags information with the FeatureBits information we
7166 // updated above.
7167 getTargetStreamer().updateABIInfo(*this);
7168
7169 // If printing assembly, use the recently updated ABI Flags information.
7170 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7171 // emitted later).
7172 getTargetStreamer().emitDirectiveModuleHardFloat();
7173
7174 // If this is not the end of the statement, report an error.
7175 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7176 reportParseError("unexpected token, expected end of statement");
7177 return false;
7178 }
7179
7180 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007181 } else {
7182 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7183 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007184}
7185
7186/// parseDirectiveModuleFP
7187/// ::= =32
7188/// ::= =xx
7189/// ::= =64
7190bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007191 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007192 MCAsmLexer &Lexer = getLexer();
7193
7194 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007195 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007196 return false;
7197 }
7198 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007199
Daniel Sanders7e527422014-07-10 13:38:23 +00007200 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007201 if (!parseFpABIValue(FpABI, ".module"))
7202 return false;
7203
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007204 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007205 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007206 return false;
7207 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007208
Toma Tabacua64e5402015-06-25 12:44:38 +00007209 // Synchronize the abiflags information with the FeatureBits information we
7210 // changed above.
7211 getTargetStreamer().updateABIInfo(*this);
7212
7213 // If printing assembly, use the recently updated abiflags information.
7214 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7215 // emitted at the end).
7216 getTargetStreamer().emitDirectiveModuleFP();
7217
Daniel Sanders7e527422014-07-10 13:38:23 +00007218 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007219 return false;
7220}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007221
Daniel Sanders7e527422014-07-10 13:38:23 +00007222bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007223 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007224 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007225 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007226 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007227
7228 if (Lexer.is(AsmToken::Identifier)) {
7229 StringRef Value = Parser.getTok().getString();
7230 Parser.Lex();
7231
7232 if (Value != "xx") {
7233 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7234 return false;
7235 }
7236
7237 if (!isABI_O32()) {
7238 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7239 return false;
7240 }
7241
Daniel Sanders7e527422014-07-10 13:38:23 +00007242 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007243 if (ModuleLevelOptions) {
7244 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7245 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7246 } else {
7247 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7248 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7249 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007250 return true;
7251 }
7252
7253 if (Lexer.is(AsmToken::Integer)) {
7254 unsigned Value = Parser.getTok().getIntVal();
7255 Parser.Lex();
7256
7257 if (Value != 32 && Value != 64) {
7258 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7259 return false;
7260 }
7261
7262 if (Value == 32) {
7263 if (!isABI_O32()) {
7264 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7265 return false;
7266 }
7267
Daniel Sanders7e527422014-07-10 13:38:23 +00007268 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007269 if (ModuleLevelOptions) {
7270 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7271 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7272 } else {
7273 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7274 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7275 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007276 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007277 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007278 if (ModuleLevelOptions) {
7279 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7280 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7281 } else {
7282 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7283 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7284 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007285 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007286
Daniel Sanders7e527422014-07-10 13:38:23 +00007287 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007288 }
7289
7290 return false;
7291}
7292
Jack Carter0b744b32012-10-04 02:29:46 +00007293bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007294 // This returns false if this function recognizes the directive
7295 // regardless of whether it is successfully handles or reports an
7296 // error. Otherwise it returns true to give the generic parser a
7297 // chance at recognizing it.
7298
Rafael Espindola961d4692014-11-11 05:18:41 +00007299 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007300 StringRef IDVal = DirectiveID.getString();
7301
Nirav Dave996fc132016-05-05 14:15:46 +00007302 if (IDVal == ".cpload") {
7303 parseDirectiveCpLoad(DirectiveID.getLoc());
7304 return false;
7305 }
7306 if (IDVal == ".cprestore") {
7307 parseDirectiveCpRestore(DirectiveID.getLoc());
7308 return false;
7309 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007310 if (IDVal == ".dword") {
7311 parseDataDirective(8, DirectiveID.getLoc());
7312 return false;
7313 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007314 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007315 StringRef SymbolName;
7316
7317 if (Parser.parseIdentifier(SymbolName)) {
7318 reportParseError("expected identifier after .ent");
7319 return false;
7320 }
7321
7322 // There's an undocumented extension that allows an integer to
7323 // follow the name of the procedure which AFAICS is ignored by GAS.
7324 // Example: .ent foo,2
7325 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7326 if (getLexer().isNot(AsmToken::Comma)) {
7327 // Even though we accept this undocumented extension for compatibility
7328 // reasons, the additional integer argument does not actually change
7329 // the behaviour of the '.ent' directive, so we would like to discourage
7330 // its use. We do this by not referring to the extended version in
7331 // error messages which are not directly related to its use.
7332 reportParseError("unexpected token, expected end of statement");
7333 return false;
7334 }
7335 Parser.Lex(); // Eat the comma.
7336 const MCExpr *DummyNumber;
7337 int64_t DummyNumberVal;
7338 // If the user was explicitly trying to use the extended version,
7339 // we still give helpful extension-related error messages.
7340 if (Parser.parseExpression(DummyNumber)) {
7341 reportParseError("expected number after comma");
7342 return false;
7343 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007344 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007345 reportParseError("expected an absolute expression after comma");
7346 return false;
7347 }
7348 }
7349
7350 // If this is not the end of the statement, report an error.
7351 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7352 reportParseError("unexpected token, expected end of statement");
7353 return false;
7354 }
7355
Jim Grosbach6f482002015-05-18 18:43:14 +00007356 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007357
7358 getTargetStreamer().emitDirectiveEnt(*Sym);
7359 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007360 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007361 return false;
7362 }
7363
Jack Carter07c818d2013-01-25 01:31:34 +00007364 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007365 StringRef SymbolName;
7366
7367 if (Parser.parseIdentifier(SymbolName)) {
7368 reportParseError("expected identifier after .end");
7369 return false;
7370 }
7371
7372 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7373 reportParseError("unexpected token, expected end of statement");
7374 return false;
7375 }
7376
7377 if (CurrentFn == nullptr) {
7378 reportParseError(".end used without .ent");
7379 return false;
7380 }
7381
7382 if ((SymbolName != CurrentFn->getName())) {
7383 reportParseError(".end symbol does not match .ent symbol");
7384 return false;
7385 }
7386
7387 getTargetStreamer().emitDirectiveEnd(SymbolName);
7388 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007389 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007390 return false;
7391 }
7392
Jack Carter07c818d2013-01-25 01:31:34 +00007393 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007394 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7395 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007396 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007397 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7398 reportParseError("expected stack register");
7399 return false;
7400 }
7401
7402 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7403 if (!StackRegOpnd.isGPRAsmReg()) {
7404 reportParseError(StackRegOpnd.getStartLoc(),
7405 "expected general purpose register");
7406 return false;
7407 }
7408 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7409
7410 if (Parser.getTok().is(AsmToken::Comma))
7411 Parser.Lex();
7412 else {
7413 reportParseError("unexpected token, expected comma");
7414 return false;
7415 }
7416
7417 // Parse the frame size.
7418 const MCExpr *FrameSize;
7419 int64_t FrameSizeVal;
7420
7421 if (Parser.parseExpression(FrameSize)) {
7422 reportParseError("expected frame size value");
7423 return false;
7424 }
7425
Jim Grosbach13760bd2015-05-30 01:25:56 +00007426 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007427 reportParseError("frame size not an absolute expression");
7428 return false;
7429 }
7430
7431 if (Parser.getTok().is(AsmToken::Comma))
7432 Parser.Lex();
7433 else {
7434 reportParseError("unexpected token, expected comma");
7435 return false;
7436 }
7437
7438 // Parse the return register.
7439 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007440 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007441 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7442 reportParseError("expected return register");
7443 return false;
7444 }
7445
7446 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7447 if (!ReturnRegOpnd.isGPRAsmReg()) {
7448 reportParseError(ReturnRegOpnd.getStartLoc(),
7449 "expected general purpose register");
7450 return false;
7451 }
7452
7453 // If this is not the end of the statement, report an error.
7454 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7455 reportParseError("unexpected token, expected end of statement");
7456 return false;
7457 }
7458
7459 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7460 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007461 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007462 return false;
7463 }
7464
Jack Carter07c818d2013-01-25 01:31:34 +00007465 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007466 parseDirectiveSet();
7467 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007468 }
7469
Daniel Sandersd97a6342014-08-13 10:07:34 +00007470 if (IDVal == ".mask" || IDVal == ".fmask") {
7471 // .mask bitmask, frame_offset
7472 // bitmask: One bit for each register used.
7473 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7474 // first register is expected to be saved.
7475 // Examples:
7476 // .mask 0x80000000, -4
7477 // .fmask 0x80000000, -4
7478 //
Jack Carterbe332172012-09-07 00:48:02 +00007479
Daniel Sandersd97a6342014-08-13 10:07:34 +00007480 // Parse the bitmask
7481 const MCExpr *BitMask;
7482 int64_t BitMaskVal;
7483
7484 if (Parser.parseExpression(BitMask)) {
7485 reportParseError("expected bitmask value");
7486 return false;
7487 }
7488
Jim Grosbach13760bd2015-05-30 01:25:56 +00007489 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007490 reportParseError("bitmask not an absolute expression");
7491 return false;
7492 }
7493
7494 if (Parser.getTok().is(AsmToken::Comma))
7495 Parser.Lex();
7496 else {
7497 reportParseError("unexpected token, expected comma");
7498 return false;
7499 }
7500
7501 // Parse the frame_offset
7502 const MCExpr *FrameOffset;
7503 int64_t FrameOffsetVal;
7504
7505 if (Parser.parseExpression(FrameOffset)) {
7506 reportParseError("expected frame offset value");
7507 return false;
7508 }
7509
Jim Grosbach13760bd2015-05-30 01:25:56 +00007510 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007511 reportParseError("frame offset not an absolute expression");
7512 return false;
7513 }
7514
7515 // If this is not the end of the statement, report an error.
7516 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7517 reportParseError("unexpected token, expected end of statement");
7518 return false;
7519 }
7520
7521 if (IDVal == ".mask")
7522 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7523 else
7524 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007525 return false;
7526 }
7527
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007528 if (IDVal == ".nan")
7529 return parseDirectiveNaN();
7530
Jack Carter07c818d2013-01-25 01:31:34 +00007531 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007532 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007533 return false;
7534 }
7535
Rafael Espindolab59fb732014-03-28 18:50:26 +00007536 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007537 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007538 return false;
7539 }
7540
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007541 if (IDVal == ".dtprelword") {
7542 parseDirectiveDtpRelWord();
7543 return false;
7544 }
7545
7546 if (IDVal == ".dtpreldword") {
7547 parseDirectiveDtpRelDWord();
7548 return false;
7549 }
7550
7551 if (IDVal == ".tprelword") {
7552 parseDirectiveTpRelWord();
7553 return false;
7554 }
7555
7556 if (IDVal == ".tpreldword") {
7557 parseDirectiveTpRelDWord();
7558 return false;
7559 }
7560
Jack Carter07c818d2013-01-25 01:31:34 +00007561 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007562 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00007563 return false;
7564 }
7565
Scott Egertond1aeb052016-02-15 16:11:51 +00007566 if (IDVal == ".hword") {
7567 parseDataDirective(2, DirectiveID.getLoc());
7568 return false;
7569 }
7570
Nirav Dave996fc132016-05-05 14:15:46 +00007571 if (IDVal == ".option") {
7572 parseDirectiveOption();
7573 return false;
7574 }
Jack Carter0cd3c192014-01-06 23:27:31 +00007575
7576 if (IDVal == ".abicalls") {
7577 getTargetStreamer().emitDirectiveAbiCalls();
7578 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007579 Error(Parser.getTok().getLoc(),
7580 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007581 }
7582 return false;
7583 }
7584
Nirav Dave996fc132016-05-05 14:15:46 +00007585 if (IDVal == ".cpsetup") {
7586 parseDirectiveCPSetup();
7587 return false;
7588 }
7589 if (IDVal == ".cpreturn") {
7590 parseDirectiveCPReturn();
7591 return false;
7592 }
7593 if (IDVal == ".module") {
7594 parseDirectiveModule();
7595 return false;
7596 }
7597 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
7598 parseInternalDirectiveReallowModule();
7599 return false;
7600 }
7601 if (IDVal == ".insn") {
7602 parseInsnDirective();
7603 return false;
7604 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007605 if (IDVal == ".rdata") {
7606 parseRSectionDirective(".rodata");
7607 return false;
7608 }
Nirav Dave996fc132016-05-05 14:15:46 +00007609 if (IDVal == ".sbss") {
7610 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
7611 return false;
7612 }
7613 if (IDVal == ".sdata") {
7614 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
7615 return false;
7616 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00007617
Rafael Espindola870c4e92012-01-11 03:56:41 +00007618 return true;
7619}
7620
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00007621bool MipsAsmParser::parseInternalDirectiveReallowModule() {
7622 // If this is not the end of the statement, report an error.
7623 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7624 reportParseError("unexpected token, expected end of statement");
7625 return false;
7626 }
7627
7628 getTargetStreamer().reallowModuleDirective();
7629
7630 getParser().Lex(); // Eat EndOfStatement token.
7631 return false;
7632}
7633
Rafael Espindola870c4e92012-01-11 03:56:41 +00007634extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00007635 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
7636 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
7637 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
7638 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00007639}
Jack Carterb4dbc172012-09-05 23:34:03 +00007640
7641#define GET_REGISTER_MATCHER
7642#define GET_MATCHER_IMPLEMENTATION
7643#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00007644
7645bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
7646 // Find the appropriate table for this asm variant.
7647 const MatchEntry *Start, *End;
7648 switch (VariantID) {
7649 default: llvm_unreachable("invalid variant!");
7650 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
7651 }
7652 // Search the table.
7653 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
7654 return MnemonicRange.first != MnemonicRange.second;
7655}