blob: f7467e9de4abbe185e8622e317e29a6c6f5d83ea [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenkodde94e42017-01-30 23:21:32 +000010#include "MCTargetDesc/MipsABIFlagsSection.h"
Eric Christophera5762812015-01-26 17:33:46 +000011#include "MCTargetDesc/MipsABIInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000012#include "MCTargetDesc/MipsBaseInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000013#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000014#include "MCTargetDesc/MipsMCTargetDesc.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Zoran Jovanovic375b60d2017-05-30 09:33:43 +000016#include "llvm/ADT/APFloat.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000019#include "llvm/ADT/StringRef.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/StringSwitch.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000021#include "llvm/ADT/Triple.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000023#include "llvm/BinaryFormat/ELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000029#include "llvm/MC/MCParser/MCAsmLexer.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000032#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000033#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000034#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000035#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/MCSymbol.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000038#include "llvm/MC/MCSymbolELF.h"
39#include "llvm/MC/MCValue.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000043#include "llvm/Support/Debug.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000044#include "llvm/Support/ErrorHandling.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000045#include "llvm/Support/MathExtras.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000046#include "llvm/Support/SMLoc.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000047#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000048#include "llvm/Support/TargetRegistry.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodde94e42017-01-30 23:21:32 +000050#include <algorithm>
51#include <cassert>
52#include <cstdint>
Toma Tabacu9db22db2014-09-09 10:15:38 +000053#include <memory>
Eugene Zelenkodde94e42017-01-30 23:21:32 +000054#include <string>
55#include <utility>
Rafael Espindola870c4e92012-01-11 03:56:41 +000056
57using namespace llvm;
58
Chandler Carruthe96dd892014-04-21 22:55:11 +000059#define DEBUG_TYPE "mips-asm-parser"
60
Joey Gouly0e76fa72013-09-12 10:28:05 +000061namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000062
Joey Gouly0e76fa72013-09-12 10:28:05 +000063class MCInstrInfo;
Eugene Zelenkodde94e42017-01-30 23:21:32 +000064
65} // end namespace llvm
Joey Gouly0e76fa72013-09-12 10:28:05 +000066
Rafael Espindola870c4e92012-01-11 03:56:41 +000067namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +000068
Jack Carter0b744b32012-10-04 02:29:46 +000069class MipsAssemblerOptions {
70public:
Eugene Zelenkodde94e42017-01-30 23:21:32 +000071 MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000072
Toma Tabacu9db22db2014-09-09 10:15:38 +000073 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000074 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000075 Reorder = Opts->isReorder();
76 Macro = Opts->isMacro();
77 Features = Opts->getFeatures();
78 }
79
Toma Tabacub19cf202015-04-27 13:12:59 +000080 unsigned getATRegIndex() const { return ATReg; }
81 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000082 if (Reg > 31)
83 return false;
84
85 ATReg = Reg;
86 return true;
87 }
Jack Carter0b744b32012-10-04 02:29:46 +000088
Toma Tabacu9db22db2014-09-09 10:15:38 +000089 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000090 void setReorder() { Reorder = true; }
91 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000092
Toma Tabacu9db22db2014-09-09 10:15:38 +000093 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000094 void setMacro() { Macro = true; }
95 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000096
Toma Tabacu465acfd2015-06-09 13:33:26 +000097 const FeatureBitset &getFeatures() const { return Features; }
98 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000099
Daniel Sandersf0df2212014-08-04 12:20:00 +0000100 // Set of features that are either architecture features or referenced
101 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
102 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
103 // The reason we need this mask is explained in the selectArch function.
104 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000105 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +0000106
Jack Carter0b744b32012-10-04 02:29:46 +0000107private:
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000108 unsigned ATReg = 1;
109 bool Reorder = true;
110 bool Macro = true;
Toma Tabacu465acfd2015-06-09 13:33:26 +0000111 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +0000112};
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000113
114} // end anonymous namespace
Jack Carter0b744b32012-10-04 02:29:46 +0000115
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000116const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
117 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
118 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
119 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
120 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
121 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
122 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
123 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
124 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
125};
126
Jack Carter0b744b32012-10-04 02:29:46 +0000127namespace {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000128
Rafael Espindola870c4e92012-01-11 03:56:41 +0000129class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000130 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000131 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000132 return static_cast<MipsTargetStreamer &>(TS);
133 }
134
Eric Christophera5762812015-01-26 17:33:46 +0000135 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000136 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000137 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
138 // nullptr, which indicates that no function is currently
139 // selected. This usually happens after an '.end func'
140 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000141 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000142 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000143 bool IsCpRestoreSet;
144 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000145 unsigned CpSaveLocation;
146 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
147 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Daniel Sandersef638fe2014-10-03 15:37:37 +0000149 // Print a warning along with its fix-it message at the given range.
150 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
151 SMRange Range, bool ShowColors = true);
152
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000153#define GET_ASSEMBLER_HEADER
154#include "MipsGenAsmMatcher.inc"
155
Daniel Sandersc5537422016-07-27 13:49:44 +0000156 unsigned
157 checkEarlyTargetMatchPredicate(MCInst &Inst,
158 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000159 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
160
Chad Rosier49963552012-10-13 00:26:04 +0000161 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000162 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000163 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000164 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000165
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000166 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000167 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000172
Craig Topper55bc6cb2017-02-08 02:54:12 +0000173 bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
174
David Blaikie960ea3f2014-06-08 16:18:35 +0000175 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
176 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000177
Craig Topper56c590a2014-04-29 07:58:02 +0000178 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000180 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
181 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000182 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000183 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000184 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
185 SMLoc S);
186 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
187 OperandMatchResultTy parseImm(OperandVector &Operands);
188 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
189 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000190 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
191 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
192 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000193
David Blaikie960ea3f2014-06-08 16:18:35 +0000194 bool searchSymbolAlias(OperandVector &Operands);
195
Toma Tabacu13964452014-09-04 13:23:44 +0000196 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000198 enum MacroExpanderResultTy {
199 MER_NotAMacro,
200 MER_Success,
201 MER_Fail,
202 };
Jack Carter30a59822012-10-04 04:03:53 +0000203
Matheus Almeida3813d572014-06-19 14:39:14 +0000204 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000205 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
206 MCStreamer &Out,
207 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000208
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000209 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000211
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000212 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000213 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000214 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000215
Toma Tabacuf712ede2015-06-17 14:31:51 +0000216 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
217 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000219
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000220 bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
221
Toma Tabacu00e98672015-05-01 12:19:27 +0000222 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000223 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000224
Zoran Jovanovic375b60d2017-05-30 09:33:43 +0000225 bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
226 SMLoc IDLoc, MCStreamer &Out,
227 const MCSubtargetInfo *STI);
228
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000229 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
230 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000238 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
239
240 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
241 const MCSubtargetInfo *STI, bool IsImmOpnd);
242
243 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000254
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000255 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000257
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000258 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000260 const bool Signed);
261
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000262 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000263 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000264
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000265 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
266 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000267
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000268 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
269 const MCSubtargetInfo *STI);
270
271 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000272 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000273
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000274 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000275 MCStreamer &Out, const MCSubtargetInfo *STI);
276 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
277 const MCSubtargetInfo *STI);
278 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
279 const MCSubtargetInfo *STI);
280 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
281 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000282
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000283 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
284 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000285
Simon Dardis3c82a642017-02-08 16:25:05 +0000286 bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
287 const MCSubtargetInfo *STI);
288
289 bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
290 const MCSubtargetInfo *STI);
291
292 bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
293 const MCSubtargetInfo *STI);
294
295 bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
296 const MCSubtargetInfo *STI);
297
Simon Dardisaff4d142016-10-18 14:28:00 +0000298 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
299 const MCSubtargetInfo *STI, bool IsLoad);
300
Simon Dardis43115a12016-11-21 20:30:41 +0000301 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
302 const MCSubtargetInfo *STI);
303
304 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
305 const MCSubtargetInfo *STI);
306
Simon Dardisde5ed0c2017-11-14 22:26:42 +0000307 bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
308 const MCSubtargetInfo *STI);
309
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000310 bool reportParseError(Twine ErrorMsg);
311 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000312
Jack Carterb5cf5902013-04-17 00:18:04 +0000313 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000314
315 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000316 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000317 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000318 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000319 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000320 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000321 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000322 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000323 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000324 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000325 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000326 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000327 bool parseInsnDirective();
Simon Dardis1c73fcc2017-06-22 10:41:51 +0000328 bool parseRSectionDirective(StringRef Section);
Simon Atanasyanbe186202016-02-11 06:45:54 +0000329 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000330
331 bool parseSetAtDirective();
332 bool parseSetNoAtDirective();
333 bool parseSetMacroDirective();
334 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000335 bool parseSetMsaDirective();
336 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000337 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000338 bool parseSetReorderDirective();
339 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000340 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000341 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000342 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000343 bool parseSetOddSPRegDirective();
344 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000345 bool parseSetPopDirective();
346 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000347 bool parseSetSoftFloatDirective();
348 bool parseSetHardFloatDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +0000349 bool parseSetMtDirective();
350 bool parseSetNoMtDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000351 bool parseSetNoCRCDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000352
Jack Carterd76b2372013-03-21 21:44:16 +0000353 bool parseSetAssignment();
354
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000355 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000356 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000357 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000358 bool parseDirectiveDtpRelWord();
359 bool parseDirectiveDtpRelDWord();
360 bool parseDirectiveTpRelWord();
361 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000362 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000363 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000364 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
365 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000366
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000367 bool parseInternalDirectiveReallowModule();
368
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000369 bool eatComma(StringRef ErrorStr);
370
Jack Carter1ac53222013-02-20 23:11:17 +0000371 int matchCPURegisterName(StringRef Symbol);
372
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000373 int matchHWRegsRegisterName(StringRef Symbol);
374
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000375 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000376
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000377 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000378
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000379 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000380
Jack Carter5dc8ac92013-09-25 23:50:44 +0000381 int matchMSA128RegisterName(StringRef Name);
382
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000383 int matchMSA128CtrlRegisterName(StringRef Name);
384
Jack Carterd0bd6422013-04-18 00:41:53 +0000385 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000386
Toma Tabacu89a712b2015-04-15 10:48:56 +0000387 /// Returns the internal register number for the current AT. Also checks if
388 /// the current AT is unavailable (set to $0) and gives an error if it is.
389 /// This should be used in pseudo-instruction expansions which need AT.
390 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000391
Simon Dardis3aa8a902017-02-06 12:43:46 +0000392 bool canUseATReg();
393
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000394 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
395 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000396
397 // Helper function that checks if the value of a vector index is within the
398 // boundaries of accepted values for each RegisterKind
399 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
400 bool validateMSAIndex(int Val, int RegKind);
401
Daniel Sandersf0df2212014-08-04 12:20:00 +0000402 // Selects a new architecture by updating the FeatureBits with the necessary
403 // info including implied dependencies.
404 // Internally, it clears all the feature bits related to *any* architecture
405 // and selects the new one using the ToggleFeature functionality of the
406 // MCSubtargetInfo object that handles implied dependencies. The reason we
407 // clear all the arch related bits manually is because ToggleFeature only
408 // clears the features that imply the feature being cleared and not the
409 // features implied by the feature being cleared. This is easier to see
410 // with an example:
411 // --------------------------------------------------
412 // | Feature | Implies |
413 // | -------------------------------------------------|
414 // | FeatureMips1 | None |
415 // | FeatureMips2 | FeatureMips1 |
416 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
417 // | FeatureMips4 | FeatureMips3 |
418 // | ... | |
419 // --------------------------------------------------
420 //
421 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
422 // FeatureMipsGP64 | FeatureMips1)
423 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
424 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000425 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000426 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000427 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
428 STI.setFeatureBits(FeatureBits);
429 setAvailableFeatures(
430 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000431 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000432 }
433
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000434 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000435 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000436 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000437 setAvailableFeatures(
438 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000439 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000440 }
441 }
442
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000443 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000444 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000445 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000446 setAvailableFeatures(
447 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000448 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000449 }
450 }
451
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000452 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
453 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000454 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000455 }
456
457 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
458 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000459 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000460 }
461
Rafael Espindola870c4e92012-01-11 03:56:41 +0000462public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000463 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000464 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000465 Match_RequiresDifferentOperands,
466 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000467 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000468 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000469 Match_NonZeroOperandForSync,
Simon Dardis52ae4f02018-03-07 11:39:48 +0000470 Match_NonZeroOperandForMTCX,
Simon Dardis6f83ae32017-09-14 15:17:50 +0000471 Match_RequiresPosSizeRange0_32,
472 Match_RequiresPosSizeRange33_64,
Simon Dardis55e44672017-09-14 17:27:53 +0000473 Match_RequiresPosSizeUImm6,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000474#define GET_OPERAND_DIAGNOSTIC_TYPES
475#include "MipsGenAsmMatcher.inc"
476#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000477 };
478
Akira Hatanakab11ef082015-11-14 06:35:56 +0000479 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000480 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000481 : MCTargetAsmParser(Options, sti, MII),
Daniel Sanders50f17232015-09-15 16:17:27 +0000482 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
483 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000484 MCAsmParserExtension::Initialize(parser);
485
Toma Tabacu11e14a92015-04-21 11:50:52 +0000486 parser.addAliasForDirective(".asciiz", ".asciz");
487
Jack Carterb4dbc172012-09-05 23:34:03 +0000488 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000489 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000490
Toma Tabacu9db22db2014-09-09 10:15:38 +0000491 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000492 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000494
Toma Tabacu9db22db2014-09-09 10:15:38 +0000495 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000496 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000497 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000498
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499 getTargetStreamer().updateABIInfo(*this);
500
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000501 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000502 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000503
504 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000505
Rafael Espindola699281c2016-05-18 11:58:50 +0000506 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000507
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000508 IsCpRestoreSet = false;
509 CpRestoreOffset = -1;
510
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000511 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000512 if ((TheTriple.getArch() == Triple::mips) ||
513 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000514 IsLittleEndian = false;
515 else
516 IsLittleEndian = true;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +0000517
518 if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
519 report_fatal_error("microMIPS64R6 is not supported", false);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000520 }
521
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000522 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
523 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
524
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000525 bool isGP64bit() const {
526 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
527 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000528
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000529 bool isFP64bit() const {
530 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
531 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000532
Eric Christophera5762812015-01-26 17:33:46 +0000533 const MipsABIInfo &getABI() const { return ABI; }
534 bool isABI_N32() const { return ABI.IsN32(); }
535 bool isABI_N64() const { return ABI.IsN64(); }
536 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000537 bool isABI_FPXX() const {
538 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
539 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000540
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000541 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000542 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000543 }
544
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000547 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000548
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 bool hasMips1() const {
550 return getSTI().getFeatureBits()[Mips::FeatureMips1];
551 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000552
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000553 bool hasMips2() const {
554 return getSTI().getFeatureBits()[Mips::FeatureMips2];
555 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000556
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000557 bool hasMips3() const {
558 return getSTI().getFeatureBits()[Mips::FeatureMips3];
559 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000560
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000561 bool hasMips4() const {
562 return getSTI().getFeatureBits()[Mips::FeatureMips4];
563 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000564
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000565 bool hasMips5() const {
566 return getSTI().getFeatureBits()[Mips::FeatureMips5];
567 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000568
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000570 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000571 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000572
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000574 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000576
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000577 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000578 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000579 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000580
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000581 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000582 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000583 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000584
Daniel Sanders17793142015-02-18 16:24:50 +0000585 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000586 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000587 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000588
Daniel Sanders17793142015-02-18 16:24:50 +0000589 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000590 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000591 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000592
Daniel Sanders17793142015-02-18 16:24:50 +0000593 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000594 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000595 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000596
Daniel Sanders17793142015-02-18 16:24:50 +0000597 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000598 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000599 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000600
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000601 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000602 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000603 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000604
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000605 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000606 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000607 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000608
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000609 bool hasDSP() const {
610 return getSTI().getFeatureBits()[Mips::FeatureDSP];
611 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000612
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000613 bool hasDSPR2() const {
614 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
615 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000616
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000617 bool hasDSPR3() const {
618 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
619 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000620
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000621 bool hasMSA() const {
622 return getSTI().getFeatureBits()[Mips::FeatureMSA];
623 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000624
Kai Nackee0245392015-01-27 19:11:28 +0000625 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000626 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000627 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000628
Daniel Sandersa6994442015-08-18 12:33:54 +0000629 bool inPicMode() {
630 return IsPicEnabled;
631 }
632
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000633 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000634 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000635 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000636
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000637 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000638 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000639 }
640
Eric Christophere8ae3e32015-05-07 23:10:21 +0000641 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000642 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000643 }
Simon Dardisae719c52017-07-11 18:03:20 +0000644 bool hasMT() const {
645 return getSTI().getFeatureBits()[Mips::FeatureMT];
646 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000647
Petar Jovanovic3408caf2018-03-14 14:13:31 +0000648 bool hasCRC() const {
649 return getSTI().getFeatureBits()[Mips::FeatureCRC];
650 }
651
Toma Tabacud9d344b2015-04-27 14:05:04 +0000652 /// Warn if RegIndex is the same as the current AT.
653 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000654
655 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000656
657 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000658
659 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
660 AsmToken::TokenKind OperatorToken,
661 MCContext &Ctx) override {
662 switch(OperatorToken) {
663 default:
664 llvm_unreachable("Unknown token");
665 return nullptr;
666 case AsmToken::PercentCall16:
667 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
668 case AsmToken::PercentCall_Hi:
669 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
670 case AsmToken::PercentCall_Lo:
671 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
672 case AsmToken::PercentDtprel_Hi:
673 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
674 case AsmToken::PercentDtprel_Lo:
675 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
676 case AsmToken::PercentGot:
677 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
678 case AsmToken::PercentGot_Disp:
679 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
680 case AsmToken::PercentGot_Hi:
681 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
682 case AsmToken::PercentGot_Lo:
683 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
684 case AsmToken::PercentGot_Ofst:
685 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
686 case AsmToken::PercentGot_Page:
687 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
688 case AsmToken::PercentGottprel:
689 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
690 case AsmToken::PercentGp_Rel:
691 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
692 case AsmToken::PercentHi:
693 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
694 case AsmToken::PercentHigher:
695 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
696 case AsmToken::PercentHighest:
697 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
698 case AsmToken::PercentLo:
699 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
700 case AsmToken::PercentNeg:
701 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
702 case AsmToken::PercentPcrel_Hi:
703 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
704 case AsmToken::PercentPcrel_Lo:
705 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
706 case AsmToken::PercentTlsgd:
707 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
708 case AsmToken::PercentTlsldm:
709 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
710 case AsmToken::PercentTprel_Hi:
711 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
712 case AsmToken::PercentTprel_Lo:
713 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
714 }
715 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000716};
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000717
718/// MipsOperand - Instances of this class represent a parsed Mips machine
719/// instruction.
720class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000721public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 /// Broad categories of register classes
723 /// The exact class is finalized by the render method.
724 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000725 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000726 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000727 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 RegKind_FCC = 4, /// FCC
729 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
730 RegKind_MSACtrl = 16, /// MSA control registers
731 RegKind_COP2 = 32, /// COP2
732 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
733 /// context).
734 RegKind_CCR = 128, /// CCR
735 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000736 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000737 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 /// Potentially any (e.g. $1)
739 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
740 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000741 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000742 };
743
744private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000745 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000746 k_Immediate, /// An immediate (possibly involving symbol references)
747 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000748 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000749 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000750 k_RegList, /// A physical register list
751 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000752 } Kind;
753
David Blaikie960ea3f2014-06-08 16:18:35 +0000754public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 MipsOperand(KindTy K, MipsAsmParser &Parser)
756 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
757
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000758 ~MipsOperand() override {
759 switch (Kind) {
760 case k_Immediate:
761 break;
762 case k_Memory:
763 delete Mem.Base;
764 break;
765 case k_RegList:
766 delete RegList.List;
767 case k_RegisterIndex:
768 case k_Token:
769 case k_RegPair:
770 break;
771 }
772 }
773
David Blaikie960ea3f2014-06-08 16:18:35 +0000774private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 /// For diagnostics, and checking the assembler temporary
776 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000777
Eric Christopher8996c5d2013-03-15 00:42:55 +0000778 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000779 const char *Data;
780 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000781 };
782
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000783 struct RegIdxOp {
784 unsigned Index; /// Index into the register class
785 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000786 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000788 };
789
790 struct ImmOp {
791 const MCExpr *Val;
792 };
793
794 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000795 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000796 const MCExpr *Off;
797 };
798
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000799 struct RegListOp {
800 SmallVector<unsigned, 10> *List;
801 };
802
Jack Carterb4dbc172012-09-05 23:34:03 +0000803 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000804 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000806 struct ImmOp Imm;
807 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000808 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000809 };
810
811 SMLoc StartLoc, EndLoc;
812
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000814 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
815 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000816 const MCRegisterInfo *RegInfo,
817 SMLoc S, SMLoc E,
818 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +0000819 auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 Op->RegIdx.Index = Index;
821 Op->RegIdx.RegInfo = RegInfo;
822 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000823 Op->RegIdx.Tok.Data = Str.data();
824 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 Op->StartLoc = S;
826 Op->EndLoc = E;
827 return Op;
828 }
829
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000830public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 /// Coerce the register to GPR32 and return the real register for the current
832 /// target.
833 unsigned getGPR32Reg() const {
834 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000835 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 unsigned ClassID = Mips::GPR32RegClassID;
837 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000838 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000839
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000840 /// Coerce the register to GPR32 and return the real register for the current
841 /// target.
842 unsigned getGPRMM16Reg() const {
843 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
844 unsigned ClassID = Mips::GPR32RegClassID;
845 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
846 }
847
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000848 /// Coerce the register to GPR64 and return the real register for the current
849 /// target.
850 unsigned getGPR64Reg() const {
851 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
852 unsigned ClassID = Mips::GPR64RegClassID;
853 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000854 }
855
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856private:
857 /// Coerce the register to AFGR64 and return the real register for the current
858 /// target.
859 unsigned getAFGR64Reg() const {
860 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
861 if (RegIdx.Index % 2 != 0)
862 AsmParser.Warning(StartLoc, "Float register should be even.");
863 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
864 .getRegister(RegIdx.Index / 2);
865 }
866
867 /// Coerce the register to FGR64 and return the real register for the current
868 /// target.
869 unsigned getFGR64Reg() const {
870 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
871 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
872 .getRegister(RegIdx.Index);
873 }
874
875 /// Coerce the register to FGR32 and return the real register for the current
876 /// target.
877 unsigned getFGR32Reg() const {
878 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
879 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
880 .getRegister(RegIdx.Index);
881 }
882
883 /// Coerce the register to FGRH32 and return the real register for the current
884 /// target.
885 unsigned getFGRH32Reg() const {
886 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
887 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
888 .getRegister(RegIdx.Index);
889 }
890
891 /// Coerce the register to FCC and return the real register for the current
892 /// target.
893 unsigned getFCCReg() const {
894 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
895 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
896 .getRegister(RegIdx.Index);
897 }
898
899 /// Coerce the register to MSA128 and return the real register for the current
900 /// target.
901 unsigned getMSA128Reg() const {
902 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
903 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
904 // identical
905 unsigned ClassID = Mips::MSA128BRegClassID;
906 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
907 }
908
909 /// Coerce the register to MSACtrl and return the real register for the
910 /// current target.
911 unsigned getMSACtrlReg() const {
912 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
913 unsigned ClassID = Mips::MSACtrlRegClassID;
914 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
915 }
916
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000917 /// Coerce the register to COP0 and return the real register for the
918 /// current target.
919 unsigned getCOP0Reg() const {
920 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
921 unsigned ClassID = Mips::COP0RegClassID;
922 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
923 }
924
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 /// Coerce the register to COP2 and return the real register for the
926 /// current target.
927 unsigned getCOP2Reg() const {
928 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
929 unsigned ClassID = Mips::COP2RegClassID;
930 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
931 }
932
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000933 /// Coerce the register to COP3 and return the real register for the
934 /// current target.
935 unsigned getCOP3Reg() const {
936 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
937 unsigned ClassID = Mips::COP3RegClassID;
938 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
939 }
940
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000941 /// Coerce the register to ACC64DSP and return the real register for the
942 /// current target.
943 unsigned getACC64DSPReg() const {
944 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
945 unsigned ClassID = Mips::ACC64DSPRegClassID;
946 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
947 }
948
949 /// Coerce the register to HI32DSP and return the real register for the
950 /// current target.
951 unsigned getHI32DSPReg() const {
952 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
953 unsigned ClassID = Mips::HI32DSPRegClassID;
954 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
955 }
956
957 /// Coerce the register to LO32DSP and return the real register for the
958 /// current target.
959 unsigned getLO32DSPReg() const {
960 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
961 unsigned ClassID = Mips::LO32DSPRegClassID;
962 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
963 }
964
965 /// Coerce the register to CCR and return the real register for the
966 /// current target.
967 unsigned getCCRReg() const {
968 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
969 unsigned ClassID = Mips::CCRRegClassID;
970 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
971 }
972
973 /// Coerce the register to HWRegs and return the real register for the
974 /// current target.
975 unsigned getHWRegsReg() const {
976 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
977 unsigned ClassID = Mips::HWRegsRegClassID;
978 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
979 }
980
981public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000982 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000983 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000984 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000985 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000986 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000987 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000988 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000990 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000991
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 void addRegOperands(MCInst &Inst, unsigned N) const {
993 llvm_unreachable("Use a custom parser instead");
994 }
995
Daniel Sanders21bce302014-04-01 12:35:23 +0000996 /// Render the operand to an MCInst as a GPR32
997 /// Asserts if the wrong number of operands are requested, or the operand
998 /// is not a k_RegisterIndex compatible with RegKind_GPR
Simon Dardis509da1a2017-02-13 16:06:48 +0000999 void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
1001 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1002 }
1003
1004 void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
1006 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
1007 }
1008
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001009 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001011 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001012 }
1013
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001014 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001016 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001017 }
1018
Jozef Kolek1904fa22014-11-24 14:25:53 +00001019 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001021 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +00001022 }
1023
Zoran Jovanovic41688672015-02-10 16:36:20 +00001024 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001026 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001027 }
1028
Daniel Sanders21bce302014-04-01 12:35:23 +00001029 /// Render the operand to an MCInst as a GPR64
1030 /// Asserts if the wrong number of operands are requested, or the operand
1031 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 void addGPR64AsmRegOperands(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(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 }
1036
1037 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 }
1041
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001042 void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
1044 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
1045 }
1046
1047 void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1048 assert(N == 1 && "Invalid number of operands!");
1049 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
1050 }
1051
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001052 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
1053 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001054 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 }
1056
1057 void addFGR32AsmRegOperands(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(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +00001060 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +00001061 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +00001062 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +00001063 AsmParser.getParser().printError(
1064 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1065 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 }
1067
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001068 void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
1070 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
1071 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
1072 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
1073 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
1074 "registers");
1075 }
1076
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001077 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001079 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001080 }
1081
1082 void addFCCAsmRegOperands(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(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001085 }
1086
1087 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001090 }
1091
1092 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 }
1096
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001097 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
1100 }
1101
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 }
1106
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001107 void addCOP3AsmRegOperands(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(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001110 }
1111
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 void addACC64DSPAsmRegOperands(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(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 }
1116
1117 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001119 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001120 }
1121
1122 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
1123 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001124 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001125 }
1126
1127 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001129 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 }
1131
1132 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001134 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 }
1136
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001137 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001138 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001140 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001141 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001142 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001143 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001144 Inst.addOperand(MCOperand::createImm(Imm));
1145 }
1146
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001147 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001148 void addSImmOperands(MCInst &Inst, unsigned N) const {
1149 if (isImm() && !isConstantImm()) {
1150 addExpr(Inst, getImm());
1151 return;
1152 }
1153 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1154 }
1155
1156 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001157 void addUImmOperands(MCInst &Inst, unsigned N) const {
1158 if (isImm() && !isConstantImm()) {
1159 addExpr(Inst, getImm());
1160 return;
1161 }
1162 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1163 }
1164
Daniel Sanders78e89022016-03-11 11:37:50 +00001165 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1166 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1167 assert(N == 1 && "Invalid number of operands!");
1168 int64_t Imm = getConstantImm() - Offset;
1169 Imm = SignExtend64<Bits>(Imm);
1170 Imm += Offset;
1171 Imm += AdjustOffset;
1172 Inst.addOperand(MCOperand::createImm(Imm));
1173 }
1174
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001175 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001176 assert(N == 1 && "Invalid number of operands!");
1177 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001178 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001179 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001180
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001181 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001182 assert(N == 2 && "Invalid number of operands!");
1183
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001184 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1185 ? getMemBase()->getGPR64Reg()
1186 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001187
1188 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001189 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001190 }
1191
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001192 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1193 assert(N == 2 && "Invalid number of operands!");
1194
Jim Grosbache9119e42015-05-13 18:37:00 +00001195 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001196
1197 const MCExpr *Expr = getMemOff();
1198 addExpr(Inst, Expr);
1199 }
1200
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001201 void addRegListOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
1203
1204 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001205 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001206 }
1207
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001208 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001210 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001211 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001212 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1213 Inst.addOperand(MCOperand::createReg(
1214 RegIdx.RegInfo->getRegClass(
1215 AsmParser.getABI().AreGprs64bit()
1216 ? Mips::GPR64RegClassID
1217 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1218 Inst.addOperand(MCOperand::createReg(
1219 RegIdx.RegInfo->getRegClass(
1220 AsmParser.getABI().AreGprs64bit()
1221 ? Mips::GPR64RegClassID
1222 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001223 }
1224
Zoran Jovanovic41688672015-02-10 16:36:20 +00001225 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 2 && "Invalid number of operands!");
1227 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001228 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001229 }
1230
Craig Topper56c590a2014-04-29 07:58:02 +00001231 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001232 // As a special case until we sort out the definition of div/divu, accept
1233 // $0/$zero here so that MCK_ZERO works correctly.
1234 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001235 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001236
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001238 bool isImm() const override { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001239
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001240 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001241 int64_t Res;
1242 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001243 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001244
Daniel Sanders52da7af2015-11-06 12:11:03 +00001245 bool isConstantImmz() const {
1246 return isConstantImm() && getConstantImm() == 0;
1247 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001248
Daniel Sandersea4f6532015-11-06 12:22:31 +00001249 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1250 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1251 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001252
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001253 template <unsigned Bits> bool isSImm() const {
1254 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1255 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001256
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001257 template <unsigned Bits> bool isUImm() const {
1258 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1259 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001260
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001261 template <unsigned Bits> bool isAnyImm() const {
1262 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1263 isUInt<Bits>(getConstantImm()))
1264 : isImm();
1265 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001266
Daniel Sanders78e89022016-03-11 11:37:50 +00001267 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1268 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001269 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001270
Hrvoje Varga46458d02016-02-25 12:53:29 +00001271 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1272 return isConstantImm() && getConstantImm() >= Bottom &&
1273 getConstantImm() <= Top;
1274 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001275
Craig Topper56c590a2014-04-29 07:58:02 +00001276 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001277 // Note: It's not possible to pretend that other operand kinds are tokens.
1278 // The matcher emitter checks tokens first.
1279 return Kind == k_Token;
1280 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001281
Craig Topper56c590a2014-04-29 07:58:02 +00001282 bool isMem() const override { return Kind == k_Memory; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001283
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001284 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001285 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001286 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001287
Simon Dardis4ccda502016-05-27 13:56:36 +00001288 // Allow relocation operators.
1289 // FIXME: This predicate and others need to look through binary expressions
1290 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001291 template <unsigned Bits, unsigned ShiftAmount = 0>
1292 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001293 if (!isMem())
1294 return false;
1295 if (!getMemBase()->isGPRAsmReg())
1296 return false;
1297 if (isa<MCTargetExpr>(getMemOff()) ||
1298 (isConstantMemOff() &&
1299 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1300 return true;
1301 MCValue Res;
1302 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1303 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001304 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001305
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001306 bool isMemWithGRPMM16Base() const {
1307 return isMem() && getMemBase()->isMM16AsmReg();
1308 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001309
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001310 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1311 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1312 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1313 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001314
Jozef Kolek12c69822014-12-23 16:16:33 +00001315 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1316 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1317 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1318 && (getMemBase()->getGPR32Reg() == Mips::SP);
1319 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001320
Daniel Sanderse473dc92016-05-09 13:38:25 +00001321 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1322 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1323 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1324 && (getMemBase()->getGPR32Reg() == Mips::GP);
1325 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001326
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001327 template <unsigned Bits, unsigned ShiftLeftAmount>
1328 bool isScaledUImm() const {
1329 return isConstantImm() &&
1330 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001331 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001332
Daniel Sanders97297772016-03-22 14:40:00 +00001333 template <unsigned Bits, unsigned ShiftLeftAmount>
1334 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001335 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1336 return true;
1337 // Operand can also be a symbol or symbol plus offset in case of relocations.
1338 if (Kind != k_Immediate)
1339 return false;
1340 MCValue Res;
1341 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1342 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001343 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001344
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001345 bool isRegList16() const {
1346 if (!isRegList())
1347 return false;
1348
1349 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001350 if (Size < 2 || Size > 5)
1351 return false;
1352
1353 unsigned R0 = RegList.List->front();
1354 unsigned R1 = RegList.List->back();
1355 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1356 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001357 return false;
1358
1359 int PrevReg = *RegList.List->begin();
1360 for (int i = 1; i < Size - 1; i++) {
1361 int Reg = (*(RegList.List))[i];
1362 if ( Reg != PrevReg + 1)
1363 return false;
1364 PrevReg = Reg;
1365 }
1366
1367 return true;
1368 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001369
Vladimir Medic2b953d02013-10-01 09:48:56 +00001370 bool isInvNum() const { return Kind == k_Immediate; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001371
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001372 bool isLSAImm() const {
1373 if (!isConstantImm())
1374 return false;
1375 int64_t Val = getConstantImm();
1376 return 1 <= Val && Val <= 4;
1377 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001378
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001379 bool isRegList() const { return Kind == k_RegList; }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001380
Zoran Jovanovic41688672015-02-10 16:36:20 +00001381 bool isMovePRegPair() const {
1382 if (Kind != k_RegList || RegList.List->size() != 2)
1383 return false;
1384
1385 unsigned R0 = RegList.List->front();
1386 unsigned R1 = RegList.List->back();
1387
1388 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1389 (R0 == Mips::A1 && R1 == Mips::A3) ||
1390 (R0 == Mips::A2 && R1 == Mips::A3) ||
1391 (R0 == Mips::A0 && R1 == Mips::S5) ||
1392 (R0 == Mips::A0 && R1 == Mips::S6) ||
1393 (R0 == Mips::A0 && R1 == Mips::A1) ||
1394 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001395 (R0 == Mips::A0 && R1 == Mips::A3) ||
1396 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1397 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1398 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1399 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1400 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1401 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1402 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1403 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001404 return true;
1405
1406 return false;
1407 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001408
1409 StringRef getToken() const {
1410 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001411 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001412 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001413
Zlatko Buljanba553a62016-05-09 08:07:28 +00001414 bool isRegPair() const {
1415 return Kind == k_RegPair && RegIdx.Index <= 30;
1416 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001417
Craig Topper56c590a2014-04-29 07:58:02 +00001418 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001419 // As a special case until we sort out the definition of div/divu, accept
1420 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001421 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1422 RegIdx.Kind & RegKind_GPR)
1423 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001424
Daniel Sanders976d9382016-07-05 13:38:40 +00001425 llvm_unreachable("Invalid access!");
1426 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001427 }
1428
Jack Carterb4dbc172012-09-05 23:34:03 +00001429 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001430 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001431 return Imm.Val;
1432 }
1433
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001434 int64_t getConstantImm() const {
1435 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001436 int64_t Value = 0;
1437 (void)Val->evaluateAsAbsolute(Value);
1438 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001439 }
1440
1441 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001442 assert((Kind == k_Memory) && "Invalid access!");
1443 return Mem.Base;
1444 }
1445
1446 const MCExpr *getMemOff() const {
1447 assert((Kind == k_Memory) && "Invalid access!");
1448 return Mem.Off;
1449 }
1450
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001451 int64_t getConstantMemOff() const {
1452 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1453 }
1454
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001455 const SmallVectorImpl<unsigned> &getRegList() const {
1456 assert((Kind == k_RegList) && "Invalid access!");
1457 return *(RegList.List);
1458 }
1459
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001460 unsigned getRegPair() const {
1461 assert((Kind == k_RegPair) && "Invalid access!");
1462 return RegIdx.Index;
1463 }
1464
David Blaikie960ea3f2014-06-08 16:18:35 +00001465 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1466 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001467 auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001468 Op->Tok.Data = Str.data();
1469 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001470 Op->StartLoc = S;
1471 Op->EndLoc = S;
1472 return Op;
1473 }
1474
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001475 /// Create a numeric register (e.g. $1). The exact register remains
1476 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001477 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001478 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1479 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001480 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001481 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001482 }
1483
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001484 /// Create a register that is definitely a GPR.
1485 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001486 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001487 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1488 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1489 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001490 }
1491
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001492 /// Create a register that is definitely a FGR.
1493 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001494 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001495 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1496 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1497 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001498 }
1499
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001500 /// Create a register that is definitely a HWReg.
1501 /// This is typically only used for named registers such as $hwr_cpunum.
1502 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001503 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001504 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001505 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001506 }
1507
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001508 /// Create a register that is definitely an FCC.
1509 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001510 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001511 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1512 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1513 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001514 }
1515
1516 /// Create a register that is definitely an ACC.
1517 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001518 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001519 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1520 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1521 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001522 }
1523
1524 /// Create a register that is definitely an MSA128.
1525 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001526 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001527 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1528 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1529 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001530 }
1531
1532 /// Create a register that is definitely an MSACtrl.
1533 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001534 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001535 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1536 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1537 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001538 }
1539
David Blaikie960ea3f2014-06-08 16:18:35 +00001540 static std::unique_ptr<MipsOperand>
1541 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001542 auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001543 Op->Imm.Val = Val;
1544 Op->StartLoc = S;
1545 Op->EndLoc = E;
1546 return Op;
1547 }
1548
David Blaikie960ea3f2014-06-08 16:18:35 +00001549 static std::unique_ptr<MipsOperand>
1550 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1551 SMLoc E, MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001552 auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
David Blaikie960ea3f2014-06-08 16:18:35 +00001553 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001554 Op->Mem.Off = Off;
1555 Op->StartLoc = S;
1556 Op->EndLoc = E;
1557 return Op;
1558 }
1559
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001560 static std::unique_ptr<MipsOperand>
1561 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1562 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001563 assert(Regs.size() > 0 && "Empty list not allowed");
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001564
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001565 auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001566 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001567 Op->StartLoc = StartLoc;
1568 Op->EndLoc = EndLoc;
1569 return Op;
1570 }
1571
Daniel Sandersd044e492016-05-09 13:10:57 +00001572 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1573 SMLoc S, SMLoc E,
1574 MipsAsmParser &Parser) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001575 auto Op = llvm::make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001576 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001577 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1578 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001579 Op->StartLoc = S;
1580 Op->EndLoc = E;
1581 return Op;
1582 }
1583
Simon Dardis509da1a2017-02-13 16:06:48 +00001584 bool isGPRZeroAsmReg() const {
1585 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
1586 }
1587
1588 bool isGPRNonZeroAsmReg() const {
1589 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
1590 RegIdx.Index <= 31;
1591 }
1592
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001593 bool isGPRAsmReg() const {
1594 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001595 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001596
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001597 bool isMM16AsmReg() const {
1598 if (!(isRegIdx() && RegIdx.Kind))
1599 return false;
1600 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1601 || RegIdx.Index == 16 || RegIdx.Index == 17);
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001602
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001603 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001604 bool isMM16AsmRegZero() const {
1605 if (!(isRegIdx() && RegIdx.Kind))
1606 return false;
1607 return (RegIdx.Index == 0 ||
1608 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1609 RegIdx.Index == 17);
1610 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001611
Zoran Jovanovic41688672015-02-10 16:36:20 +00001612 bool isMM16AsmRegMoveP() const {
1613 if (!(isRegIdx() && RegIdx.Kind))
1614 return false;
1615 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1616 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1617 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001618
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001619 bool isFGRAsmReg() const {
1620 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1621 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001622 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001623
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00001624 bool isStrictlyFGRAsmReg() const {
1625 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1626 return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
1627 }
1628
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001629 bool isHWRegsAsmReg() const {
1630 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001631 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001632
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001633 bool isCCRAsmReg() const {
1634 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001635 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001636
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001637 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001638 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1639 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001640 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001641 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 bool isACCAsmReg() const {
1644 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001645 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001646
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001647 bool isCOP0AsmReg() const {
1648 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1649 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001650
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001651 bool isCOP2AsmReg() const {
1652 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001653 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001654
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001655 bool isCOP3AsmReg() const {
1656 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1657 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001658
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001659 bool isMSA128AsmReg() const {
1660 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001661 }
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001662
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001663 bool isMSACtrlAsmReg() const {
1664 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001665 }
1666
Jack Carterb4dbc172012-09-05 23:34:03 +00001667 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001668 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001669 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001670 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001671
Craig Topper56c590a2014-04-29 07:58:02 +00001672 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001673 switch (Kind) {
1674 case k_Immediate:
1675 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001676 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001677 OS << ">";
1678 break;
1679 case k_Memory:
1680 OS << "Mem<";
1681 Mem.Base->print(OS);
1682 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001683 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001684 OS << ">";
1685 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001686 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001687 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1688 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001689 break;
1690 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001691 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001692 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001693 case k_RegList:
1694 OS << "RegList< ";
1695 for (auto Reg : (*RegList.List))
1696 OS << Reg << " ";
1697 OS << ">";
1698 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001699 case k_RegPair:
1700 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1701 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001702 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001703 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001704
1705 bool isValidForTie(const MipsOperand &Other) const {
1706 if (Kind != Other.Kind)
1707 return false;
1708
1709 switch (Kind) {
1710 default:
1711 llvm_unreachable("Unexpected kind");
1712 return false;
1713 case k_RegisterIndex: {
1714 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1715 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1716 return Token == OtherToken;
1717 }
1718 }
1719 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001720}; // class MipsOperand
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001721
1722} // end anonymous namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001723
Jack Carter9e65aa32013-03-22 00:05:30 +00001724namespace llvm {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001725
Jack Carter9e65aa32013-03-22 00:05:30 +00001726extern const MCInstrDesc MipsInsts[];
Eugene Zelenkodde94e42017-01-30 23:21:32 +00001727
1728} // end namespace llvm
1729
Jack Carter9e65aa32013-03-22 00:05:30 +00001730static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1731 return MipsInsts[Opcode];
1732}
1733
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001734static bool hasShortDelaySlot(unsigned Opcode) {
1735 switch (Opcode) {
1736 case Mips::JALS_MM:
1737 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001738 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001739 case Mips::BGEZALS_MM:
1740 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001741 return true;
1742 default:
1743 return false;
1744 }
1745}
1746
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001747static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1748 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1749 return &SRExpr->getSymbol();
1750 }
1751
1752 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1753 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1754 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1755
1756 if (LHSSym)
1757 return LHSSym;
1758
1759 if (RHSSym)
1760 return RHSSym;
1761
1762 return nullptr;
1763 }
1764
1765 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1766 return getSingleMCSymbol(UExpr->getSubExpr());
1767
1768 return nullptr;
1769}
1770
1771static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1772 if (isa<MCSymbolRefExpr>(Expr))
1773 return 1;
1774
1775 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1776 return countMCSymbolRefExpr(BExpr->getLHS()) +
1777 countMCSymbolRefExpr(BExpr->getRHS());
1778
1779 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1780 return countMCSymbolRefExpr(UExpr->getSubExpr());
1781
1782 return 0;
1783}
1784
Jack Carter9e65aa32013-03-22 00:05:30 +00001785bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001786 MCStreamer &Out,
1787 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001788 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001789 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001790 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001791
Jack Carter9e65aa32013-03-22 00:05:30 +00001792 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001793
1794 if (MCID.isBranch() || MCID.isCall()) {
1795 const unsigned Opcode = Inst.getOpcode();
1796 MCOperand Offset;
1797
1798 switch (Opcode) {
1799 default:
1800 break;
Kai Nackee0245392015-01-27 19:11:28 +00001801 case Mips::BBIT0:
1802 case Mips::BBIT032:
1803 case Mips::BBIT1:
1804 case Mips::BBIT132:
1805 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001806 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001807
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001808 case Mips::BEQ:
1809 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001810 case Mips::BEQ_MM:
1811 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001812 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001813 Offset = Inst.getOperand(2);
1814 if (!Offset.isImm())
1815 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001816 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001817 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001818 if (OffsetToAlignment(Offset.getImm(),
1819 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001820 return Error(IDLoc, "branch to misaligned address");
1821 break;
1822 case Mips::BGEZ:
1823 case Mips::BGTZ:
1824 case Mips::BLEZ:
1825 case Mips::BLTZ:
1826 case Mips::BGEZAL:
1827 case Mips::BLTZAL:
1828 case Mips::BC1F:
1829 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001830 case Mips::BGEZ_MM:
1831 case Mips::BGTZ_MM:
1832 case Mips::BLEZ_MM:
1833 case Mips::BLTZ_MM:
1834 case Mips::BGEZAL_MM:
1835 case Mips::BLTZAL_MM:
1836 case Mips::BC1F_MM:
1837 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001838 case Mips::BC1EQZC_MMR6:
1839 case Mips::BC1NEZC_MMR6:
1840 case Mips::BC2EQZC_MMR6:
1841 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001842 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001843 Offset = Inst.getOperand(1);
1844 if (!Offset.isImm())
1845 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001846 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001847 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001848 if (OffsetToAlignment(Offset.getImm(),
1849 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001850 return Error(IDLoc, "branch to misaligned address");
1851 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001852 case Mips::BGEC: case Mips::BGEC_MMR6:
1853 case Mips::BLTC: case Mips::BLTC_MMR6:
1854 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1855 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1856 case Mips::BEQC: case Mips::BEQC_MMR6:
1857 case Mips::BNEC: case Mips::BNEC_MMR6:
1858 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1859 Offset = Inst.getOperand(2);
1860 if (!Offset.isImm())
1861 break; // We'll deal with this situation later on when applying fixups.
1862 if (!isIntN(18, Offset.getImm()))
1863 return Error(IDLoc, "branch target out of range");
1864 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1865 return Error(IDLoc, "branch to misaligned address");
1866 break;
1867 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1868 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1869 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1870 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1871 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1872 Offset = Inst.getOperand(1);
1873 if (!Offset.isImm())
1874 break; // We'll deal with this situation later on when applying fixups.
1875 if (!isIntN(18, Offset.getImm()))
1876 return Error(IDLoc, "branch target out of range");
1877 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1878 return Error(IDLoc, "branch to misaligned address");
1879 break;
1880 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1881 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1882 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1883 Offset = Inst.getOperand(1);
1884 if (!Offset.isImm())
1885 break; // We'll deal with this situation later on when applying fixups.
1886 if (!isIntN(23, Offset.getImm()))
1887 return Error(IDLoc, "branch target out of range");
1888 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1889 return Error(IDLoc, "branch to misaligned address");
1890 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001891 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001892 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001893 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001894 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001895 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1896 Offset = Inst.getOperand(1);
1897 if (!Offset.isImm())
1898 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001899 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001900 return Error(IDLoc, "branch target out of range");
1901 if (OffsetToAlignment(Offset.getImm(), 2LL))
1902 return Error(IDLoc, "branch to misaligned address");
1903 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001904 }
1905 }
1906
Daniel Sandersa84989a2014-06-16 13:25:35 +00001907 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1908 // We still accept it but it is a normal nop.
1909 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1910 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1911 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1912 "nop instruction");
1913 }
1914
Kai Nackee0245392015-01-27 19:11:28 +00001915 if (hasCnMips()) {
1916 const unsigned Opcode = Inst.getOpcode();
1917 MCOperand Opnd;
1918 int Imm;
1919
1920 switch (Opcode) {
1921 default:
1922 break;
1923
1924 case Mips::BBIT0:
1925 case Mips::BBIT032:
1926 case Mips::BBIT1:
1927 case Mips::BBIT132:
1928 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1929 // The offset is handled above
1930 Opnd = Inst.getOperand(1);
1931 if (!Opnd.isImm())
1932 return Error(IDLoc, "expected immediate operand kind");
1933 Imm = Opnd.getImm();
1934 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1935 Opcode == Mips::BBIT1 ? 63 : 31))
1936 return Error(IDLoc, "immediate operand value out of range");
1937 if (Imm > 31) {
1938 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1939 : Mips::BBIT132);
1940 Inst.getOperand(1).setImm(Imm - 32);
1941 }
1942 break;
1943
Kai Nackee0245392015-01-27 19:11:28 +00001944 case Mips::SEQi:
1945 case Mips::SNEi:
1946 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1947 Opnd = Inst.getOperand(2);
1948 if (!Opnd.isImm())
1949 return Error(IDLoc, "expected immediate operand kind");
1950 Imm = Opnd.getImm();
1951 if (!isInt<10>(Imm))
1952 return Error(IDLoc, "immediate operand value out of range");
1953 break;
1954 }
1955 }
1956
Simon Dardis509da1a2017-02-13 16:06:48 +00001957 // Warn on division by zero. We're checking here as all instructions get
1958 // processed here, not just the macros that need expansion.
1959 //
1960 // The MIPS backend models most of the divison instructions and macros as
1961 // three operand instructions. The pre-R6 divide instructions however have
1962 // two operands and explicitly define HI/LO as part of the instruction,
1963 // not in the operands.
1964 unsigned FirstOp = 1;
1965 unsigned SecondOp = 2;
1966 switch (Inst.getOpcode()) {
1967 default:
1968 break;
1969 case Mips::SDivIMacro:
1970 case Mips::UDivIMacro:
1971 case Mips::DSDivIMacro:
1972 case Mips::DUDivIMacro:
1973 if (Inst.getOperand(2).getImm() == 0) {
1974 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
1975 Inst.getOperand(1).getReg() == Mips::ZERO_64)
1976 Warning(IDLoc, "dividing zero by zero");
1977 else
1978 Warning(IDLoc, "division by zero");
1979 }
1980 break;
1981 case Mips::DSDIV:
1982 case Mips::SDIV:
1983 case Mips::UDIV:
1984 case Mips::DUDIV:
1985 case Mips::UDIV_MM:
1986 case Mips::SDIV_MM:
1987 FirstOp = 0;
1988 SecondOp = 1;
Simon Pilgrimd0536342017-07-08 15:26:26 +00001989 LLVM_FALLTHROUGH;
Simon Dardis509da1a2017-02-13 16:06:48 +00001990 case Mips::SDivMacro:
1991 case Mips::DSDivMacro:
1992 case Mips::UDivMacro:
1993 case Mips::DUDivMacro:
1994 case Mips::DIV:
1995 case Mips::DIVU:
1996 case Mips::DDIV:
1997 case Mips::DDIVU:
1998 case Mips::DIVU_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00001999 case Mips::DIV_MMR6:
Simon Dardis509da1a2017-02-13 16:06:48 +00002000 if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
2001 Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
2002 if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
2003 Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
2004 Warning(IDLoc, "dividing zero by zero");
2005 else
2006 Warning(IDLoc, "division by zero");
2007 }
2008 break;
2009 }
2010
Simon Atanasyan50485142016-12-12 17:40:26 +00002011 // For PIC code convert unconditional jump to unconditional branch.
2012 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
2013 inPicMode()) {
2014 MCInst BInst;
2015 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
2016 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2017 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
2018 BInst.addOperand(Inst.getOperand(0));
2019 Inst = BInst;
2020 }
2021
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002022 // This expansion is not in a function called by tryExpandInstruction()
2023 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002024 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
2025 inPicMode()) {
2026 warnIfNoMacro(IDLoc);
2027
2028 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
2029
2030 // We can do this expansion if there's only 1 symbol in the argument
2031 // expression.
2032 if (countMCSymbolRefExpr(JalExpr) > 1)
2033 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
2034
2035 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002036 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002037 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
2038
2039 // FIXME: Add support for label+offset operands (currently causes an error).
2040 // FIXME: Add support for forward-declared local symbols.
2041 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00002042 if (JalSym->isInSection() || JalSym->isTemporary() ||
2043 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002044 if (isABI_O32()) {
2045 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002046 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002047 // R_(MICRO)MIPS_GOT16 label
2048 // addiu $25, $25, 0
2049 // R_(MICRO)MIPS_LO16 label
2050 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002051 const MCExpr *Got16RelocExpr =
2052 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
2053 const MCExpr *Lo16RelocExpr =
2054 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002055
Daniel Sandersa736b372016-04-29 13:33:12 +00002056 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
2057 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
2058 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
2059 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002060 } else if (isABI_N32() || isABI_N64()) {
2061 // If it's a local symbol and the N32/N64 ABIs are being used,
2062 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00002063 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002064 // R_(MICRO)MIPS_GOT_DISP label
2065 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002066 const MCExpr *GotDispRelocExpr =
2067 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002068
Daniel Sandersa736b372016-04-29 13:33:12 +00002069 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
2070 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
2071 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002072 }
2073 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00002074 // If it's an external/weak symbol, we expand to:
2075 // lw/ld $25, 0($gp)
2076 // R_(MICRO)MIPS_CALL16 label
2077 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002078 const MCExpr *Call16RelocExpr =
2079 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002080
Daniel Sandersa736b372016-04-29 13:33:12 +00002081 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
2082 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002083 }
2084
2085 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002086 if (IsCpRestoreSet && inMicroMipsMode())
2087 JalrInst.setOpcode(Mips::JALRS_MM);
2088 else
2089 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002090 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
2091 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
2092
2093 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
2094 // This relocation is supposed to be an optimization hint for the linker
2095 // and is not necessary for correctness.
2096
2097 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002098 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00002099 }
2100
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00002101 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
2102 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002103 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 // reference or immediate we may have to expand instructions.
2105 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002106 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00002107 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2108 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002109 MCOperand &Op = Inst.getOperand(i);
2110 if (Op.isImm()) {
2111 int MemOffset = Op.getImm();
2112 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002114 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00002115 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002116 }
2117 } else if (Op.isExpr()) {
2118 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002119 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002120 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00002121 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00002122 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002124 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002125 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002126 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002127 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002128 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00002129 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00002130 }
2131 }
2132 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002133 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00002134 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00002135
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002136 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00002137 if (MCID.mayLoad()) {
2138 // Try to create 16-bit GP relative load instruction.
2139 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2140 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
2141 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
2142 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
2143 MCOperand &Op = Inst.getOperand(i);
2144 if (Op.isImm()) {
2145 int MemOffset = Op.getImm();
2146 MCOperand &DstReg = Inst.getOperand(0);
2147 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00002148 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00002149 getContext().getRegisterInfo()->getRegClass(
2150 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00002151 (BaseReg.getReg() == Mips::GP ||
2152 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002153
Daniel Sandersa736b372016-04-29 13:33:12 +00002154 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
2155 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00002156 return false;
2157 }
2158 }
2159 }
2160 } // for
2161 } // if load
2162
2163 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
2164
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002165 MCOperand Opnd;
2166 int Imm;
2167
2168 switch (Inst.getOpcode()) {
2169 default:
2170 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00002171 case Mips::ADDIUSP_MM:
2172 Opnd = Inst.getOperand(0);
2173 if (!Opnd.isImm())
2174 return Error(IDLoc, "expected immediate operand kind");
2175 Imm = Opnd.getImm();
2176 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
2177 Imm % 4 != 0)
2178 return Error(IDLoc, "immediate operand value out of range");
2179 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00002180 case Mips::SLL16_MM:
2181 case Mips::SRL16_MM:
2182 Opnd = Inst.getOperand(2);
2183 if (!Opnd.isImm())
2184 return Error(IDLoc, "expected immediate operand kind");
2185 Imm = Opnd.getImm();
2186 if (Imm < 1 || Imm > 8)
2187 return Error(IDLoc, "immediate operand value out of range");
2188 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00002189 case Mips::LI16_MM:
2190 Opnd = Inst.getOperand(1);
2191 if (!Opnd.isImm())
2192 return Error(IDLoc, "expected immediate operand kind");
2193 Imm = Opnd.getImm();
2194 if (Imm < -1 || Imm > 126)
2195 return Error(IDLoc, "immediate operand value out of range");
2196 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00002197 case Mips::ADDIUR2_MM:
2198 Opnd = Inst.getOperand(2);
2199 if (!Opnd.isImm())
2200 return Error(IDLoc, "expected immediate operand kind");
2201 Imm = Opnd.getImm();
2202 if (!(Imm == 1 || Imm == -1 ||
2203 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
2204 return Error(IDLoc, "immediate operand value out of range");
2205 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00002206 case Mips::ANDI16_MM:
2207 Opnd = Inst.getOperand(2);
2208 if (!Opnd.isImm())
2209 return Error(IDLoc, "expected immediate operand kind");
2210 Imm = Opnd.getImm();
2211 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
2212 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
2213 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
2214 return Error(IDLoc, "immediate operand value out of range");
2215 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002216 case Mips::LBU16_MM:
2217 Opnd = Inst.getOperand(2);
2218 if (!Opnd.isImm())
2219 return Error(IDLoc, "expected immediate operand kind");
2220 Imm = Opnd.getImm();
2221 if (Imm < -1 || Imm > 14)
2222 return Error(IDLoc, "immediate operand value out of range");
2223 break;
2224 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002225 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002226 Opnd = Inst.getOperand(2);
2227 if (!Opnd.isImm())
2228 return Error(IDLoc, "expected immediate operand kind");
2229 Imm = Opnd.getImm();
2230 if (Imm < 0 || Imm > 15)
2231 return Error(IDLoc, "immediate operand value out of range");
2232 break;
2233 case Mips::LHU16_MM:
2234 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002235 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002236 Opnd = Inst.getOperand(2);
2237 if (!Opnd.isImm())
2238 return Error(IDLoc, "expected immediate operand kind");
2239 Imm = Opnd.getImm();
2240 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2241 return Error(IDLoc, "immediate operand value out of range");
2242 break;
2243 case Mips::LW16_MM:
2244 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002245 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002246 Opnd = Inst.getOperand(2);
2247 if (!Opnd.isImm())
2248 return Error(IDLoc, "expected immediate operand kind");
2249 Imm = Opnd.getImm();
2250 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2251 return Error(IDLoc, "immediate operand value out of range");
2252 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002253 case Mips::ADDIUPC_MM:
2254 MCOperand Opnd = Inst.getOperand(1);
2255 if (!Opnd.isImm())
2256 return Error(IDLoc, "expected immediate operand kind");
2257 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002258 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002259 return Error(IDLoc, "immediate operand value out of range");
2260 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002261 }
2262 }
2263
Daniel Sandersd8c07762016-04-18 12:35:36 +00002264 bool FillDelaySlot =
2265 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2266 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002267 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002268
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002269 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002270 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002271 switch (ExpandResult) {
2272 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002273 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002274 break;
2275 case MER_Success:
2276 break;
2277 case MER_Fail:
2278 return true;
2279 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002280
Daniel Sanderscda908a2016-05-16 09:10:13 +00002281 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2282 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002283 if (inMicroMipsMode()) {
Daniel Sanderscda908a2016-05-16 09:10:13 +00002284 TOut.setUsesMicroMips();
Aleksandar Beserminji590f0792017-11-24 14:00:47 +00002285 TOut.updateABIInfo(*this);
2286 }
Daniel Sanderscda908a2016-05-16 09:10:13 +00002287
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002288 // If this instruction has a delay slot and .set reorder is active,
2289 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002290 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002291 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2292 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002293 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002294
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002295 if ((Inst.getOpcode() == Mips::JalOneReg ||
2296 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2297 isPicAndNotNxxAbi()) {
2298 if (IsCpRestoreSet) {
2299 // We need a NOP between the JALR and the LW:
2300 // If .set reorder has been used, we've already emitted a NOP.
2301 // If .set noreorder has been used, we need to emit a NOP at this point.
2302 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002303 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2304 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002305
2306 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002307 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002308 } else
2309 Warning(IDLoc, "no .cprestore used in PIC mode");
2310 }
2311
Jack Carter9e65aa32013-03-22 00:05:30 +00002312 return false;
2313}
2314
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002315MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002316MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2317 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002318 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002319 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002320 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002321 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002322 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002323 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002324 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002325 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002326 case Mips::LoadAddrImm64:
2327 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2328 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2329 "expected immediate operand kind");
2330
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002331 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2332 Inst.getOperand(1),
2333 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002334 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002335 ? MER_Fail
2336 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002337 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002338 case Mips::LoadAddrReg64:
2339 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2340 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2341 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2342 "expected immediate operand kind");
2343
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002344 return expandLoadAddress(Inst.getOperand(0).getReg(),
2345 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2346 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002347 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002348 ? MER_Fail
2349 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002350 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002351 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002352 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2353 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002354 case Mips::SWM_MM:
2355 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002356 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2357 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002358 case Mips::JalOneReg:
2359 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002360 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002361 case Mips::BneImm:
2362 case Mips::BeqImm:
Simon Dardis08ce5fb2017-02-02 16:13:49 +00002363 case Mips::BEQLImmMacro:
2364 case Mips::BNELImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002365 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002366 case Mips::BLT:
2367 case Mips::BLE:
2368 case Mips::BGE:
2369 case Mips::BGT:
2370 case Mips::BLTU:
2371 case Mips::BLEU:
2372 case Mips::BGEU:
2373 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002374 case Mips::BLTL:
2375 case Mips::BLEL:
2376 case Mips::BGEL:
2377 case Mips::BGTL:
2378 case Mips::BLTUL:
2379 case Mips::BLEUL:
2380 case Mips::BGEUL:
2381 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002382 case Mips::BLTImmMacro:
2383 case Mips::BLEImmMacro:
2384 case Mips::BGEImmMacro:
2385 case Mips::BGTImmMacro:
2386 case Mips::BLTUImmMacro:
2387 case Mips::BLEUImmMacro:
2388 case Mips::BGEUImmMacro:
2389 case Mips::BGTUImmMacro:
2390 case Mips::BLTLImmMacro:
2391 case Mips::BLELImmMacro:
2392 case Mips::BGELImmMacro:
2393 case Mips::BGTLImmMacro:
2394 case Mips::BLTULImmMacro:
2395 case Mips::BLEULImmMacro:
2396 case Mips::BGEULImmMacro:
2397 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002398 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002399 case Mips::SDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002400 case Mips::SDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002401 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2402 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002403 case Mips::DSDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002404 case Mips::DSDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002405 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2406 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002407 case Mips::UDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002408 case Mips::UDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002409 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2410 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002411 case Mips::DUDivMacro:
Simon Dardis12850ee2017-01-31 10:49:24 +00002412 case Mips::DUDivIMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002413 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2414 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002415 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002416 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2417 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002418 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002419 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002420 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002421 case Mips::PseudoTRUNC_W_D:
2422 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2423 : MER_Success;
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00002424
2425 case Mips::LoadImmSingleGPR:
2426 return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
2427 ? MER_Fail
2428 : MER_Success;
2429 case Mips::LoadImmSingleFGR:
2430 return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
2431 ? MER_Fail
2432 : MER_Success;
2433 case Mips::LoadImmDoubleGPR:
2434 return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
2435 ? MER_Fail
2436 : MER_Success;
2437 case Mips::LoadImmDoubleFGR:
2438 return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
2439 ? MER_Fail
2440 : MER_Success;
2441 case Mips::LoadImmDoubleFGR_32:
2442 return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
2443 ? MER_Fail
2444 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002445 case Mips::Ulh:
2446 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2447 case Mips::Ulhu:
2448 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002449 case Mips::Ush:
2450 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002451 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002452 case Mips::Usw:
2453 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002454 case Mips::NORImm:
Simon Dardise3cceed2017-02-28 15:55:23 +00002455 case Mips::NORImm64:
2456 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2457 case Mips::SLTImm64:
2458 if (isInt<16>(Inst.getOperand(2).getImm())) {
2459 Inst.setOpcode(Mips::SLTi64);
2460 return MER_NotAMacro;
2461 }
2462 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2463 case Mips::SLTUImm64:
2464 if (isInt<16>(Inst.getOperand(2).getImm())) {
2465 Inst.setOpcode(Mips::SLTiu64);
2466 return MER_NotAMacro;
2467 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002468 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisd410fc82017-02-23 12:40:58 +00002469 case Mips::ADDi: case Mips::ADDi_MM:
2470 case Mips::ADDiu: case Mips::ADDiu_MM:
2471 case Mips::SLTi: case Mips::SLTi_MM:
2472 case Mips::SLTiu: case Mips::SLTiu_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002473 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2474 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2475 int64_t ImmValue = Inst.getOperand(2).getImm();
2476 if (isInt<16>(ImmValue))
2477 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002478 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2479 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002480 }
2481 return MER_NotAMacro;
Simon Dardisaa208812017-02-24 14:34:32 +00002482 case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
2483 case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
2484 case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002485 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2486 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2487 int64_t ImmValue = Inst.getOperand(2).getImm();
2488 if (isUInt<16>(ImmValue))
2489 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002490 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2491 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002492 }
2493 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002494 case Mips::ROL:
2495 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002496 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002497 case Mips::ROLImm:
2498 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002499 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002500 case Mips::DROL:
2501 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002502 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002503 case Mips::DROLImm:
2504 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002505 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002506 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002507 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardis3c82a642017-02-08 16:25:05 +00002508 case Mips::MULImmMacro:
2509 case Mips::DMULImmMacro:
2510 return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2511 case Mips::MULOMacro:
2512 case Mips::DMULOMacro:
2513 return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2514 case Mips::MULOUMacro:
2515 case Mips::DMULOUMacro:
2516 return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2517 case Mips::DMULMacro:
2518 return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002519 case Mips::LDMacro:
2520 case Mips::SDMacro:
2521 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2522 Inst.getOpcode() == Mips::LDMacro)
2523 ? MER_Fail
2524 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002525 case Mips::SEQMacro:
2526 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2527 case Mips::SEQIMacro:
2528 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisde5ed0c2017-11-14 22:26:42 +00002529 case Mips::MFTC0: case Mips::MTTC0:
2530 case Mips::MFTGPR: case Mips::MTTGPR:
2531 case Mips::MFTLO: case Mips::MTTLO:
2532 case Mips::MFTHI: case Mips::MTTHI:
2533 case Mips::MFTACX: case Mips::MTTACX:
2534 case Mips::MFTDSP: case Mips::MTTDSP:
2535 case Mips::MFTC1: case Mips::MTTC1:
2536 case Mips::MFTHC1: case Mips::MTTHC1:
2537 case Mips::CFTC1: case Mips::CTTC1:
2538 return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 }
Jack Carter30a59822012-10-04 04:03:53 +00002540}
Jack Carter92995f12012-10-06 00:53:28 +00002541
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002542bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002543 MCStreamer &Out,
2544 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002545 MipsTargetStreamer &TOut = getTargetStreamer();
2546
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002547 // Create a JALR instruction which is going to replace the pseudo-JAL.
2548 MCInst JalrInst;
2549 JalrInst.setLoc(IDLoc);
2550 const MCOperand FirstRegOp = Inst.getOperand(0);
2551 const unsigned Opcode = Inst.getOpcode();
2552
2553 if (Opcode == Mips::JalOneReg) {
2554 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002555 if (IsCpRestoreSet && inMicroMipsMode()) {
2556 JalrInst.setOpcode(Mips::JALRS16_MM);
2557 JalrInst.addOperand(FirstRegOp);
2558 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002559 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002560 JalrInst.addOperand(FirstRegOp);
2561 } else {
2562 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002563 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002564 JalrInst.addOperand(FirstRegOp);
2565 }
2566 } else if (Opcode == Mips::JalTwoReg) {
2567 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002568 if (IsCpRestoreSet && inMicroMipsMode())
2569 JalrInst.setOpcode(Mips::JALRS_MM);
2570 else
2571 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002572 JalrInst.addOperand(FirstRegOp);
2573 const MCOperand SecondRegOp = Inst.getOperand(1);
2574 JalrInst.addOperand(SecondRegOp);
2575 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002576 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002577
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002578 // If .set reorder is active and branch instruction has a delay slot,
2579 // emit a NOP after it.
2580 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002581 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2582 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2583 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002584
2585 return false;
2586}
2587
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002588/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002589template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002590 unsigned BitNum = findFirstSet(x);
2591
2592 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2593}
2594
2595/// Load (or add) an immediate into a register.
2596///
2597/// @param ImmValue The immediate to load.
2598/// @param DstReg The register that will hold the immediate.
2599/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2600/// for a simple initialization.
2601/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2602/// @param IsAddress True if the immediate represents an address. False if it
2603/// is an integer.
2604/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002605bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002606 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002607 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2608 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002609 MipsTargetStreamer &TOut = getTargetStreamer();
2610
Toma Tabacu00e98672015-05-01 12:19:27 +00002611 if (!Is32BitImm && !isGP64bit()) {
2612 Error(IDLoc, "instruction requires a 64-bit architecture");
2613 return true;
2614 }
2615
Daniel Sanders03f9c012015-07-14 12:24:22 +00002616 if (Is32BitImm) {
2617 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2618 // Sign extend up to 64-bit so that the predicates match the hardware
2619 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2620 // true.
2621 ImmValue = SignExtend64<32>(ImmValue);
2622 } else {
2623 Error(IDLoc, "instruction requires a 32-bit immediate");
2624 return true;
2625 }
2626 }
2627
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002628 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2629 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2630
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002631 bool UseSrcReg = false;
2632 if (SrcReg != Mips::NoRegister)
2633 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002634
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002635 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002636 if (UseSrcReg &&
2637 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002638 // At this point we need AT to perform the expansions and we exit if it is
2639 // not available.
2640 unsigned ATReg = getATReg(IDLoc);
2641 if (!ATReg)
2642 return true;
2643 TmpReg = ATReg;
2644 }
2645
Daniel Sanders03f9c012015-07-14 12:24:22 +00002646 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002647 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002648 SrcReg = ZeroReg;
2649
2650 // This doesn't quite follow the usual ABI expectations for N32 but matches
2651 // traditional assembler behaviour. N32 would normally use addiu for both
2652 // integers and addresses.
2653 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002654 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002655 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002656 }
2657
Daniel Sandersa736b372016-04-29 13:33:12 +00002658 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002659 return false;
2660 }
2661
2662 if (isUInt<16>(ImmValue)) {
2663 unsigned TmpReg = DstReg;
2664 if (SrcReg == DstReg) {
2665 TmpReg = getATReg(IDLoc);
2666 if (!TmpReg)
2667 return true;
2668 }
2669
Daniel Sandersa736b372016-04-29 13:33:12 +00002670 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002671 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002672 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002673 return false;
2674 }
2675
2676 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002677 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002678
Toma Tabacu79588102015-04-29 10:19:56 +00002679 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2680 uint16_t Bits15To0 = ImmValue & 0xffff;
Toma Tabacua3d056f2015-05-15 09:42:11 +00002681 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002682 // Traditional behaviour seems to special case this particular value. It's
2683 // not clear why other masks are handled differently.
2684 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002685 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2686 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002687 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002688 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002689 return false;
2690 }
2691
2692 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002693 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002694 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2695 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002696 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002697 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002698 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002699 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002700 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002701 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002702
Daniel Sandersa736b372016-04-29 13:33:12 +00002703 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002704 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002705 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002706 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002707 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002708 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002709 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002710
2711 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2712 if (Is32BitImm) {
2713 Error(IDLoc, "instruction requires a 32-bit immediate");
2714 return true;
2715 }
2716
2717 // Traditionally, these immediates are shifted as little as possible and as
2718 // such we align the most significant bit to bit 15 of our temporary.
2719 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2720 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2721 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2722 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002723 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2724 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002725
2726 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002727 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002728
2729 return false;
2730 }
2731
2732 warnIfNoMacro(IDLoc);
2733
2734 // The remaining case is packed with a sequence of dsll and ori with zeros
2735 // being omitted and any neighbouring dsll's being coalesced.
2736 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2737
2738 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2739 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002740 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002741 return false;
2742
2743 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2744 // skip it and defer the shift to the next chunk.
2745 unsigned ShiftCarriedForwards = 16;
2746 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2747 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2748
2749 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002750 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2751 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002752 ShiftCarriedForwards = 0;
2753 }
2754
2755 ShiftCarriedForwards += 16;
2756 }
2757 ShiftCarriedForwards -= 16;
2758
2759 // Finish any remaining shifts left by trailing zeros.
2760 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002761 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002762
2763 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002764 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002765
Matheus Almeida3813d572014-06-19 14:39:14 +00002766 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002767}
Jack Carter92995f12012-10-06 00:53:28 +00002768
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002769bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002770 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002771 const MCOperand &ImmOp = Inst.getOperand(1);
2772 assert(ImmOp.isImm() && "expected immediate operand kind");
2773 const MCOperand &DstRegOp = Inst.getOperand(0);
2774 assert(DstRegOp.isReg() && "expected register operand kind");
2775
2776 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002777 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002778 return true;
2779
2780 return false;
2781}
2782
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002783bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2784 const MCOperand &Offset,
2785 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002786 MCStreamer &Out,
2787 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002788 // la can't produce a usable address when addresses are 64-bit.
2789 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2790 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2791 // We currently can't do this because we depend on the equality
2792 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2793 Error(IDLoc, "la used to load 64-bit address");
2794 // Continue as if we had 'dla' instead.
2795 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002796 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002797 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002798
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002799 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002800 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002801 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002802 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002803 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002804
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002805 if (!Offset.isImm())
2806 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002807 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002808
Scott Egerton24557012016-01-21 15:11:01 +00002809 if (!ABI.ArePtrs64bit()) {
2810 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2811 Is32BitAddress = true;
2812 }
2813
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002814 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002815 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002816}
2817
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002818bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2819 unsigned DstReg, unsigned SrcReg,
2820 bool Is32BitSym, SMLoc IDLoc,
2821 MCStreamer &Out,
2822 const MCSubtargetInfo *STI) {
Simon Dardisda96c432017-06-30 15:44:27 +00002823 // FIXME: These expansions do not respect -mxgot.
Daniel Sandersa736b372016-04-29 13:33:12 +00002824 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002825 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002826 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002827
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002828 if (inPicMode() && ABI.IsO32()) {
2829 MCValue Res;
2830 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2831 Error(IDLoc, "expected relocatable expression");
2832 return true;
2833 }
2834 if (Res.getSymB() != nullptr) {
2835 Error(IDLoc, "expected relocatable expression with only one symbol");
2836 return true;
2837 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002838
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002839 // The case where the result register is $25 is somewhat special. If the
2840 // symbol in the final relocation is external and not modified with a
2841 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2842 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Simon Dardis3e0d39e2017-06-27 10:11:11 +00002843 Res.getConstant() == 0 &&
2844 !(Res.getSymA()->getSymbol().isInSection() ||
2845 Res.getSymA()->getSymbol().isTemporary() ||
2846 (Res.getSymA()->getSymbol().isELF() &&
2847 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2848 ELF::STB_LOCAL))) {
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002849 const MCExpr *CallExpr =
2850 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2851 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2852 MCOperand::createExpr(CallExpr), IDLoc, STI);
2853 return false;
2854 }
2855
2856 // The remaining cases are:
2857 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2858 // >addiu $tmp, $tmp, %lo(offset)
2859 // >addiu $rd, $tmp, $rs
2860 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2861 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2862 // >addiu $rd, $tmp, $rs
2863 // The addiu's marked with a '>' may be omitted if they are redundant. If
2864 // this happens then the last instruction must use $rd as the result
2865 // register.
2866 const MipsMCExpr *GotExpr =
2867 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2868 const MCExpr *LoExpr = nullptr;
2869 if (Res.getSymA()->getSymbol().isInSection() ||
2870 Res.getSymA()->getSymbol().isTemporary())
2871 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2872 else if (Res.getConstant() != 0) {
2873 // External symbols fully resolve the symbol with just the %got(symbol)
2874 // but we must still account for any offset to the symbol for expressions
2875 // like symbol+8.
2876 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2877 }
2878
2879 unsigned TmpReg = DstReg;
2880 if (UseSrcReg &&
2881 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2882 SrcReg)) {
2883 // If $rs is the same as $rd, we need to use AT.
2884 // If it is not available we exit.
2885 unsigned ATReg = getATReg(IDLoc);
2886 if (!ATReg)
2887 return true;
2888 TmpReg = ATReg;
2889 }
2890
2891 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2892 MCOperand::createExpr(GotExpr), IDLoc, STI);
2893
2894 if (LoExpr)
2895 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2896 IDLoc, STI);
2897
2898 if (UseSrcReg)
2899 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2900
2901 return false;
2902 }
2903
Simon Dardisda96c432017-06-30 15:44:27 +00002904 if (inPicMode() && ABI.ArePtrs64bit()) {
2905 MCValue Res;
2906 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2907 Error(IDLoc, "expected relocatable expression");
2908 return true;
2909 }
2910 if (Res.getSymB() != nullptr) {
2911 Error(IDLoc, "expected relocatable expression with only one symbol");
2912 return true;
2913 }
2914
2915 // The case where the result register is $25 is somewhat special. If the
2916 // symbol in the final relocation is external and not modified with a
2917 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2918 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2919 Res.getConstant() == 0 &&
2920 !(Res.getSymA()->getSymbol().isInSection() ||
2921 Res.getSymA()->getSymbol().isTemporary() ||
2922 (Res.getSymA()->getSymbol().isELF() &&
2923 cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
2924 ELF::STB_LOCAL))) {
2925 const MCExpr *CallExpr =
2926 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2927 TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
2928 MCOperand::createExpr(CallExpr), IDLoc, STI);
2929 return false;
2930 }
2931
2932 // The remaining cases are:
2933 // Small offset: ld $tmp, %got_disp(symbol)($gp)
2934 // >daddiu $tmp, $tmp, offset
2935 // >daddu $rd, $tmp, $rs
2936 // The daddiu's marked with a '>' may be omitted if they are redundant. If
2937 // this happens then the last instruction must use $rd as the result
2938 // register.
2939 const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
2940 Res.getSymA(),
2941 getContext());
2942 const MCExpr *LoExpr = nullptr;
2943 if (Res.getConstant() != 0) {
2944 // Symbols fully resolve with just the %got_disp(symbol) but we
2945 // must still account for any offset to the symbol for
2946 // expressions like symbol+8.
2947 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2948
2949 // FIXME: Offsets greater than 16 bits are not yet implemented.
2950 // FIXME: The correct range is a 32-bit sign-extended number.
2951 if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
2952 Error(IDLoc, "macro instruction uses large offset, which is not "
2953 "currently supported");
2954 return true;
2955 }
2956 }
2957
2958 unsigned TmpReg = DstReg;
2959 if (UseSrcReg &&
2960 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2961 SrcReg)) {
2962 // If $rs is the same as $rd, we need to use AT.
2963 // If it is not available we exit.
2964 unsigned ATReg = getATReg(IDLoc);
2965 if (!ATReg)
2966 return true;
2967 TmpReg = ATReg;
2968 }
2969
2970 TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
2971 MCOperand::createExpr(GotExpr), IDLoc, STI);
2972
2973 if (LoExpr)
2974 TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2975 IDLoc, STI);
2976
2977 if (UseSrcReg)
2978 TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2979
2980 return false;
2981 }
2982
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002983 const MipsMCExpr *HiExpr =
2984 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2985 const MipsMCExpr *LoExpr =
2986 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002987
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002988 // This is the 64-bit symbol address expansion.
2989 if (ABI.ArePtrs64bit() && isGP64bit()) {
Simon Dardis3aa8a902017-02-06 12:43:46 +00002990 // We need AT for the 64-bit expansion in the cases where the optional
2991 // source register is the destination register and for the superscalar
2992 // scheduled form.
2993 //
2994 // If it is not available we exit if the destination is the same as the
2995 // source register.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002996
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002997 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002998 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002999 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00003000 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003001
Simon Dardis3aa8a902017-02-06 12:43:46 +00003002 bool RdRegIsRsReg =
3003 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
3004
3005 if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
3006 unsigned ATReg = getATReg(IDLoc);
3007
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003008 // If $rs is the same as $rd:
3009 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
3010 // daddiu $at, $at, %higher(sym)
3011 // dsll $at, $at, 16
3012 // daddiu $at, $at, %hi(sym)
3013 // dsll $at, $at, 16
3014 // daddiu $at, $at, %lo(sym)
3015 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00003016 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3017 STI);
3018 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3019 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3020 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3021 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3022 IDLoc, STI);
3023 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3024 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3025 IDLoc, STI);
3026 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003027
3028 return false;
Simon Dardis3aa8a902017-02-06 12:43:46 +00003029 } else if (canUseATReg() && !RdRegIsRsReg) {
3030 unsigned ATReg = getATReg(IDLoc);
3031
3032 // If the $rs is different from $rd or if $rs isn't specified and we
3033 // have $at available:
3034 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3035 // lui $at, %hi(sym)
3036 // daddiu $rd, $rd, %higher(sym)
3037 // daddiu $at, $at, %lo(sym)
3038 // dsll32 $rd, $rd, 0
3039 // daddu $rd, $rd, $at
3040 // (daddu $rd, $rd, $rs)
3041 //
3042 // Which is preferred for superscalar issue.
3043 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3044 STI);
3045 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3046 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3047 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3048 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
3049 IDLoc, STI);
3050 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
3051 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
3052 if (UseSrcReg)
3053 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3054
3055 return false;
3056 } else if (!canUseATReg() && !RdRegIsRsReg) {
3057 // Otherwise, synthesize the address in the destination register
3058 // serially:
3059 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
3060 // daddiu $rd, $rd, %higher(sym)
3061 // dsll $rd, $rd, 16
3062 // daddiu $rd, $rd, %hi(sym)
3063 // dsll $rd, $rd, 16
3064 // daddiu $rd, $rd, %lo(sym)
3065 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
3066 STI);
3067 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3068 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3069 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3070 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3071 MCOperand::createExpr(HiExpr), IDLoc, STI);
3072 TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
3073 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
3074 MCOperand::createExpr(LoExpr), IDLoc, STI);
3075 if (UseSrcReg)
3076 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
3077
3078 return false;
3079 } else {
3080 // We have a case where SrcReg == DstReg and we don't have $at
3081 // available. We can't expand this case, so error out appropriately.
3082 assert(SrcReg == DstReg && !canUseATReg() &&
3083 "Could have expanded dla but didn't?");
3084 reportParseError(IDLoc,
3085 "pseudo-instruction requires $at, which is not available");
3086 return true;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003087 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003088 }
3089
3090 // And now, the 32-bit symbol address expansion:
3091 // If $rs is the same as $rd:
3092 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
3093 // ori $at, $at, %lo(sym)
3094 // addu $rd, $at, $rd
3095 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
3096 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
3097 // ori $rd, $rd, %lo(sym)
3098 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00003099 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00003100 if (UseSrcReg &&
3101 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003102 // If $rs is the same as $rd, we need to use AT.
3103 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00003104 unsigned ATReg = getATReg(IDLoc);
3105 if (!ATReg)
3106 return true;
3107 TmpReg = ATReg;
3108 }
3109
Daniel Sandersa736b372016-04-29 13:33:12 +00003110 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3111 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
3112 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00003113
Toma Tabacufb9d1252015-06-22 12:08:39 +00003114 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00003115 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003116 else
Scott Egerton24557012016-01-21 15:11:01 +00003117 assert(
3118 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00003119
Toma Tabacu674825c2015-06-16 12:16:24 +00003120 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00003121}
3122
Zoran Jovanovic375b60d2017-05-30 09:33:43 +00003123// Each double-precision register DO-D15 overlaps with two of the single
3124// precision registers F0-F31. As an example, all of the following hold true:
3125// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
3126static unsigned nextReg(unsigned Reg) {
3127 if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
3128 return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
3129 switch (Reg) {
3130 default: llvm_unreachable("Unknown register in assembly macro expansion!");
3131 case Mips::ZERO: return Mips::AT;
3132 case Mips::AT: return Mips::V0;
3133 case Mips::V0: return Mips::V1;
3134 case Mips::V1: return Mips::A0;
3135 case Mips::A0: return Mips::A1;
3136 case Mips::A1: return Mips::A2;
3137 case Mips::A2: return Mips::A3;
3138 case Mips::A3: return Mips::T0;
3139 case Mips::T0: return Mips::T1;
3140 case Mips::T1: return Mips::T2;
3141 case Mips::T2: return Mips::T3;
3142 case Mips::T3: return Mips::T4;
3143 case Mips::T4: return Mips::T5;
3144 case Mips::T5: return Mips::T6;
3145 case Mips::T6: return Mips::T7;
3146 case Mips::T7: return Mips::S0;
3147 case Mips::S0: return Mips::S1;
3148 case Mips::S1: return Mips::S2;
3149 case Mips::S2: return Mips::S3;
3150 case Mips::S3: return Mips::S4;
3151 case Mips::S4: return Mips::S5;
3152 case Mips::S5: return Mips::S6;
3153 case Mips::S6: return Mips::S7;
3154 case Mips::S7: return Mips::T8;
3155 case Mips::T8: return Mips::T9;
3156 case Mips::T9: return Mips::K0;
3157 case Mips::K0: return Mips::K1;
3158 case Mips::K1: return Mips::GP;
3159 case Mips::GP: return Mips::SP;
3160 case Mips::SP: return Mips::FP;
3161 case Mips::FP: return Mips::RA;
3162 case Mips::RA: return Mips::ZERO;
3163 case Mips::D0: return Mips::F1;
3164 case Mips::D1: return Mips::F3;
3165 case Mips::D2: return Mips::F5;
3166 case Mips::D3: return Mips::F7;
3167 case Mips::D4: return Mips::F9;
3168 case Mips::D5: return Mips::F11;
3169 case Mips::D6: return Mips::F13;
3170 case Mips::D7: return Mips::F15;
3171 case Mips::D8: return Mips::F17;
3172 case Mips::D9: return Mips::F19;
3173 case Mips::D10: return Mips::F21;
3174 case Mips::D11: return Mips::F23;
3175 case Mips::D12: return Mips::F25;
3176 case Mips::D13: return Mips::F27;
3177 case Mips::D14: return Mips::F29;
3178 case Mips::D15: return Mips::F31;
3179 }
3180}
3181
3182// FIXME: This method is too general. In principle we should compute the number
3183// of instructions required to synthesize the immediate inline compared to
3184// synthesizing the address inline and relying on non .text sections.
3185// For static O32 and N32 this may yield a small benefit, for static N64 this is
3186// likely to yield a much larger benefit as we have to synthesize a 64bit
3187// address to load a 64 bit value.
3188bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
3189 MCSymbol *Sym) {
3190 unsigned ATReg = getATReg(IDLoc);
3191 if (!ATReg)
3192 return true;
3193
3194 if(IsPicEnabled) {
3195 const MCExpr *GotSym =
3196 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3197 const MipsMCExpr *GotExpr =
3198 MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
3199
3200 if(isABI_O32() || isABI_N32()) {
3201 TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3202 IDLoc, STI);
3203 } else { //isABI_N64()
3204 TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
3205 IDLoc, STI);
3206 }
3207 } else { //!IsPicEnabled
3208 const MCExpr *HiSym =
3209 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3210 const MipsMCExpr *HiExpr =
3211 MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
3212
3213 // FIXME: This is technically correct but gives a different result to gas,
3214 // but gas is incomplete there (it has a fixme noting it doesn't work with
3215 // 64-bit addresses).
3216 // FIXME: With -msym32 option, the address expansion for N64 should probably
3217 // use the O32 / N32 case. It's safe to use the 64 address expansion as the
3218 // symbol's value is considered sign extended.
3219 if(isABI_O32() || isABI_N32()) {
3220 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
3221 } else { //isABI_N64()
3222 const MCExpr *HighestSym =
3223 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3224 const MipsMCExpr *HighestExpr =
3225 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
3226 const MCExpr *HigherSym =
3227 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3228 const MipsMCExpr *HigherExpr =
3229 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
3230
3231 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
3232 STI);
3233 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3234 MCOperand::createExpr(HigherExpr), IDLoc, STI);
3235 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3236 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
3237 IDLoc, STI);
3238 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
3239 }
3240 }
3241 return false;
3242}
3243
3244bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
3245 bool Is64FPU, SMLoc IDLoc,
3246 MCStreamer &Out,
3247 const MCSubtargetInfo *STI) {
3248 MipsTargetStreamer &TOut = getTargetStreamer();
3249 assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3250 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3251 "Invalid instruction operand.");
3252
3253 unsigned FirstReg = Inst.getOperand(0).getReg();
3254 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3255
3256 uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3257 // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3258 // exponent field), convert it to double (e.g. 1 to 1.0)
3259 if ((HiImmOp64 & 0x7ff00000) == 0) {
3260 APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3261 ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3262 }
3263
3264 uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
3265 HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
3266
3267 if (IsSingle) {
3268 // Conversion of a double in an uint64_t to a float in a uint32_t,
3269 // retaining the bit pattern of a float.
3270 uint32_t ImmOp32;
3271 double doubleImm = BitsToDouble(ImmOp64);
3272 float tmp_float = static_cast<float>(doubleImm);
3273 ImmOp32 = FloatToBits(tmp_float);
3274
3275 if (IsGPR) {
3276 if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
3277 Out, STI))
3278 return true;
3279 return false;
3280 } else {
3281 unsigned ATReg = getATReg(IDLoc);
3282 if (!ATReg)
3283 return true;
3284 if (LoImmOp64 == 0) {
3285 if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
3286 Out, STI))
3287 return true;
3288 TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
3289 return false;
3290 }
3291
3292 MCSection *CS = getStreamer().getCurrentSectionOnly();
3293 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3294 // where appropriate.
3295 MCSection *ReadOnlySection = getContext().getELFSection(
3296 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3297
3298 MCSymbol *Sym = getContext().createTempSymbol();
3299 const MCExpr *LoSym =
3300 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3301 const MipsMCExpr *LoExpr =
3302 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3303
3304 getStreamer().SwitchSection(ReadOnlySection);
3305 getStreamer().EmitLabel(Sym, IDLoc);
3306 getStreamer().EmitIntValue(ImmOp32, 4);
3307 getStreamer().SwitchSection(CS);
3308
3309 if(emitPartialAddress(TOut, IDLoc, Sym))
3310 return true;
3311 TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
3312 MCOperand::createExpr(LoExpr), IDLoc, STI);
3313 }
3314 return false;
3315 }
3316
3317 // if(!IsSingle)
3318 unsigned ATReg = getATReg(IDLoc);
3319 if (!ATReg)
3320 return true;
3321
3322 if (IsGPR) {
3323 if (LoImmOp64 == 0) {
3324 if(isABI_N32() || isABI_N64()) {
3325 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
3326 IDLoc, Out, STI))
3327 return true;
3328 return false;
3329 } else {
3330 if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
3331 IDLoc, Out, STI))
3332 return true;
3333
3334 if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
3335 IDLoc, Out, STI))
3336 return true;
3337 return false;
3338 }
3339 }
3340
3341 MCSection *CS = getStreamer().getCurrentSectionOnly();
3342 MCSection *ReadOnlySection = getContext().getELFSection(
3343 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3344
3345 MCSymbol *Sym = getContext().createTempSymbol();
3346 const MCExpr *LoSym =
3347 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3348 const MipsMCExpr *LoExpr =
3349 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3350
3351 getStreamer().SwitchSection(ReadOnlySection);
3352 getStreamer().EmitLabel(Sym, IDLoc);
3353 getStreamer().EmitIntValue(HiImmOp64, 4);
3354 getStreamer().EmitIntValue(LoImmOp64, 4);
3355 getStreamer().SwitchSection(CS);
3356
3357 if(emitPartialAddress(TOut, IDLoc, Sym))
3358 return true;
3359 if(isABI_N64())
3360 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
3361 MCOperand::createExpr(LoExpr), IDLoc, STI);
3362 else
3363 TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
3364 MCOperand::createExpr(LoExpr), IDLoc, STI);
3365
3366 if(isABI_N32() || isABI_N64())
3367 TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
3368 else {
3369 TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
3370 TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
3371 }
3372 return false;
3373 } else { // if(!IsGPR && !IsSingle)
3374 if ((LoImmOp64 == 0) &&
3375 !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
3376 // FIXME: In the case where the constant is zero, we can load the
3377 // register directly from the zero register.
3378 if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
3379 Out, STI))
3380 return true;
3381 if (isABI_N32() || isABI_N64())
3382 TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
3383 else if (hasMips32r2()) {
3384 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3385 TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
3386 } else {
3387 TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
3388 TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3389 }
3390 return false;
3391 }
3392
3393 MCSection *CS = getStreamer().getCurrentSectionOnly();
3394 // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
3395 // where appropriate.
3396 MCSection *ReadOnlySection = getContext().getELFSection(
3397 ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
3398
3399 MCSymbol *Sym = getContext().createTempSymbol();
3400 const MCExpr *LoSym =
3401 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
3402 const MipsMCExpr *LoExpr =
3403 MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
3404
3405 getStreamer().SwitchSection(ReadOnlySection);
3406 getStreamer().EmitLabel(Sym, IDLoc);
3407 getStreamer().EmitIntValue(HiImmOp64, 4);
3408 getStreamer().EmitIntValue(LoImmOp64, 4);
3409 getStreamer().SwitchSection(CS);
3410
3411 if(emitPartialAddress(TOut, IDLoc, Sym))
3412 return true;
3413 TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
3414 MCOperand::createExpr(LoExpr), IDLoc, STI);
3415 }
3416 return false;
3417}
3418
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003419bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
3420 MCStreamer &Out,
3421 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003422 MipsTargetStreamer &TOut = getTargetStreamer();
3423
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00003424 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
3425 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003426
3427 MCOperand Offset = Inst.getOperand(0);
3428 if (Offset.isExpr()) {
3429 Inst.clear();
3430 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003431 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3432 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3433 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003434 } else {
3435 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00003436 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003437 // If offset fits into 11 bits then this instruction becomes microMIPS
3438 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00003439 if (inMicroMipsMode())
3440 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003441 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00003442 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00003443 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003444 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00003445 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003446 Inst.clear();
3447 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003448 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3449 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
3450 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003451 }
3452 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003453 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003454
Zoran Jovanovicada70912015-09-07 11:56:37 +00003455 // If .set reorder is active and branch instruction has a delay slot,
3456 // emit a NOP after it.
3457 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3458 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00003459 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00003460
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00003461 return false;
3462}
3463
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003464bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3465 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003466 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00003467 const MCOperand &DstRegOp = Inst.getOperand(0);
3468 assert(DstRegOp.isReg() && "expected register operand kind");
3469
3470 const MCOperand &ImmOp = Inst.getOperand(1);
3471 assert(ImmOp.isImm() && "expected immediate operand kind");
3472
3473 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00003474 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
3475 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00003476
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003477 bool IsLikely = false;
3478
Toma Tabacue1e460d2015-06-11 10:36:10 +00003479 unsigned OpCode = 0;
3480 switch(Inst.getOpcode()) {
3481 case Mips::BneImm:
3482 OpCode = Mips::BNE;
3483 break;
3484 case Mips::BeqImm:
3485 OpCode = Mips::BEQ;
3486 break;
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003487 case Mips::BEQLImmMacro:
3488 OpCode = Mips::BEQL;
3489 IsLikely = true;
3490 break;
3491 case Mips::BNELImmMacro:
3492 OpCode = Mips::BNEL;
3493 IsLikely = true;
3494 break;
Toma Tabacue1e460d2015-06-11 10:36:10 +00003495 default:
3496 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
3497 break;
3498 }
3499
3500 int64_t ImmValue = ImmOp.getImm();
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003501 if (ImmValue == 0) {
3502 if (IsLikely) {
3503 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
3504 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3505 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3506 } else
3507 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
3508 STI);
3509 } else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00003510 warnIfNoMacro(IDLoc);
3511
3512 unsigned ATReg = getATReg(IDLoc);
3513 if (!ATReg)
3514 return true;
3515
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003516 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003517 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00003518 return true;
3519
Simon Dardis08ce5fb2017-02-02 16:13:49 +00003520 if (IsLikely) {
3521 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
3522 MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
3523 TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
3524 } else
3525 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00003526 }
3527 return false;
3528}
3529
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003530void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00003531 const MCSubtargetInfo *STI, bool IsLoad,
3532 bool IsImmOpnd) {
3533 if (IsLoad) {
3534 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3535 return;
Scott Egertond65377d2016-03-17 10:37:51 +00003536 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00003537 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
3538}
3539
3540void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3541 const MCSubtargetInfo *STI, bool IsImmOpnd) {
3542 MipsTargetStreamer &TOut = getTargetStreamer();
3543
3544 unsigned DstReg = Inst.getOperand(0).getReg();
3545 unsigned BaseReg = Inst.getOperand(1).getReg();
3546
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00003547 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00003548 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
3549 unsigned DstRegClassID =
3550 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3551 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3552 (DstRegClassID == Mips::GPR64RegClassID);
3553
3554 if (IsImmOpnd) {
3555 // Try to use DstReg as the temporary.
3556 if (IsGPR && (BaseReg != DstReg)) {
3557 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3558 Inst.getOperand(2).getImm(), DstReg, IDLoc,
3559 STI);
3560 return;
3561 }
3562
Matheus Almeida7de68e72014-06-18 14:46:05 +00003563 // At this point we need AT to perform the expansions and we exit if it is
3564 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00003565 unsigned ATReg = getATReg(IDLoc);
3566 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00003567 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00003568
3569 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
3570 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
3571 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00003572 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00003573
Daniel Sandersfba875f2016-04-29 13:43:45 +00003574 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003575 MCOperand LoOperand = MCOperand::createExpr(
3576 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3577 MCOperand HiOperand = MCOperand::createExpr(
3578 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003579
3580 // Try to use DstReg as the temporary.
3581 if (IsGPR && (BaseReg != DstReg)) {
3582 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3583 LoOperand, DstReg, IDLoc, STI);
3584 return;
3585 }
3586
3587 // At this point we need AT to perform the expansions and we exit if it is
3588 // not available.
3589 unsigned ATReg = getATReg(IDLoc);
3590 if (!ATReg)
3591 return;
3592
3593 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
3594 LoOperand, ATReg, IDLoc, STI);
3595}
3596
3597void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3598 const MCSubtargetInfo *STI,
3599 bool IsImmOpnd) {
3600 MipsTargetStreamer &TOut = getTargetStreamer();
3601
3602 unsigned SrcReg = Inst.getOperand(0).getReg();
3603 unsigned BaseReg = Inst.getOperand(1).getReg();
3604
Daniel Sanders241c6792016-05-12 14:01:50 +00003605 if (IsImmOpnd) {
3606 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
3607 Inst.getOperand(2).getImm(),
3608 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
3609 return;
3610 }
3611
Daniel Sandersfba875f2016-04-29 13:43:45 +00003612 unsigned ATReg = getATReg(IDLoc);
3613 if (!ATReg)
3614 return;
3615
Daniel Sandersfba875f2016-04-29 13:43:45 +00003616 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00003617 MCOperand LoOperand = MCOperand::createExpr(
3618 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
3619 MCOperand HiOperand = MCOperand::createExpr(
3620 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00003621 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
3622 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00003623}
3624
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003625bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
3626 MCStreamer &Out,
3627 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003628 unsigned OpNum = Inst.getNumOperands();
3629 unsigned Opcode = Inst.getOpcode();
3630 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
3631
Eugene Zelenkodde94e42017-01-30 23:21:32 +00003632 assert(Inst.getOperand(OpNum - 1).isImm() &&
3633 Inst.getOperand(OpNum - 2).isReg() &&
3634 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003635
3636 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
3637 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003638 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
3639 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
3640 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
3641 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003642 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00003643 if (inMicroMipsMode() && hasMips32r6())
3644 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
3645 else
3646 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
3647 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003648
3649 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003650 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00003651 return false;
3652}
3653
Toma Tabacu1a108322015-06-17 13:20:24 +00003654bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003655 MCStreamer &Out,
3656 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003657 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003658 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00003659 unsigned PseudoOpcode = Inst.getOpcode();
3660 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003661 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00003662 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
3663
3664 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003665 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00003666
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003667 unsigned TrgReg;
3668 if (TrgOp.isReg())
3669 TrgReg = TrgOp.getReg();
3670 else if (TrgOp.isImm()) {
3671 warnIfNoMacro(IDLoc);
3672 EmittedNoMacroWarning = true;
3673
3674 TrgReg = getATReg(IDLoc);
3675 if (!TrgReg)
3676 return true;
3677
3678 switch(PseudoOpcode) {
3679 default:
3680 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3681 case Mips::BLTImmMacro:
3682 PseudoOpcode = Mips::BLT;
3683 break;
3684 case Mips::BLEImmMacro:
3685 PseudoOpcode = Mips::BLE;
3686 break;
3687 case Mips::BGEImmMacro:
3688 PseudoOpcode = Mips::BGE;
3689 break;
3690 case Mips::BGTImmMacro:
3691 PseudoOpcode = Mips::BGT;
3692 break;
3693 case Mips::BLTUImmMacro:
3694 PseudoOpcode = Mips::BLTU;
3695 break;
3696 case Mips::BLEUImmMacro:
3697 PseudoOpcode = Mips::BLEU;
3698 break;
3699 case Mips::BGEUImmMacro:
3700 PseudoOpcode = Mips::BGEU;
3701 break;
3702 case Mips::BGTUImmMacro:
3703 PseudoOpcode = Mips::BGTU;
3704 break;
3705 case Mips::BLTLImmMacro:
3706 PseudoOpcode = Mips::BLTL;
3707 break;
3708 case Mips::BLELImmMacro:
3709 PseudoOpcode = Mips::BLEL;
3710 break;
3711 case Mips::BGELImmMacro:
3712 PseudoOpcode = Mips::BGEL;
3713 break;
3714 case Mips::BGTLImmMacro:
3715 PseudoOpcode = Mips::BGTL;
3716 break;
3717 case Mips::BLTULImmMacro:
3718 PseudoOpcode = Mips::BLTUL;
3719 break;
3720 case Mips::BLEULImmMacro:
3721 PseudoOpcode = Mips::BLEUL;
3722 break;
3723 case Mips::BGEULImmMacro:
3724 PseudoOpcode = Mips::BGEUL;
3725 break;
3726 case Mips::BGTULImmMacro:
3727 PseudoOpcode = Mips::BGTUL;
3728 break;
3729 }
3730
3731 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003732 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003733 return true;
3734 }
3735
Toma Tabacu1a108322015-06-17 13:20:24 +00003736 switch (PseudoOpcode) {
3737 case Mips::BLT:
3738 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003739 case Mips::BLTL:
3740 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003741 AcceptsEquality = false;
3742 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003743 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3744 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003745 ZeroSrcOpcode = Mips::BGTZ;
3746 ZeroTrgOpcode = Mips::BLTZ;
3747 break;
3748 case Mips::BLE:
3749 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003750 case Mips::BLEL:
3751 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003752 AcceptsEquality = true;
3753 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003754 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3755 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003756 ZeroSrcOpcode = Mips::BGEZ;
3757 ZeroTrgOpcode = Mips::BLEZ;
3758 break;
3759 case Mips::BGE:
3760 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003761 case Mips::BGEL:
3762 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003763 AcceptsEquality = true;
3764 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003765 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3766 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003767 ZeroSrcOpcode = Mips::BLEZ;
3768 ZeroTrgOpcode = Mips::BGEZ;
3769 break;
3770 case Mips::BGT:
3771 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003772 case Mips::BGTL:
3773 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003774 AcceptsEquality = false;
3775 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003776 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3777 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003778 ZeroSrcOpcode = Mips::BLTZ;
3779 ZeroTrgOpcode = Mips::BGTZ;
3780 break;
3781 default:
3782 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3783 }
3784
Toma Tabacu1a108322015-06-17 13:20:24 +00003785 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3786 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3787 if (IsSrcRegZero && IsTrgRegZero) {
3788 // FIXME: All of these Opcode-specific if's are needed for compatibility
3789 // with GAS' behaviour. However, they may not generate the most efficient
3790 // code in some circumstances.
3791 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003792 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3793 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003794 return false;
3795 }
3796 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003797 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3798 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003799 Warning(IDLoc, "branch is always taken");
3800 return false;
3801 }
3802 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003803 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3804 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003805 Warning(IDLoc, "branch is always taken");
3806 return false;
3807 }
3808 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003809 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3810 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003811 return false;
3812 }
3813 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003814 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3815 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003816 return false;
3817 }
3818 if (AcceptsEquality) {
3819 // If both registers are $0 and the pseudo-branch accepts equality, it
3820 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003821 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3822 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003823 Warning(IDLoc, "branch is always taken");
3824 return false;
3825 }
3826 // If both registers are $0 and the pseudo-branch does not accept
3827 // equality, it will never be taken, so we don't have to emit anything.
3828 return false;
3829 }
3830 if (IsSrcRegZero || IsTrgRegZero) {
3831 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3832 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3833 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3834 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3835 // the pseudo-branch will never be taken, so we don't emit anything.
3836 // This only applies to unsigned pseudo-branches.
3837 return false;
3838 }
3839 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3840 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3841 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3842 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3843 // the pseudo-branch will always be taken, so we emit an unconditional
3844 // branch.
3845 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003846 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3847 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003848 Warning(IDLoc, "branch is always taken");
3849 return false;
3850 }
3851 if (IsUnsigned) {
3852 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3853 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3854 // the pseudo-branch will be taken only when the non-zero register is
3855 // different from 0, so we emit a BNEZ.
3856 //
3857 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3858 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3859 // the pseudo-branch will be taken only when the non-zero register is
3860 // equal to 0, so we emit a BEQZ.
3861 //
3862 // Because only BLEU and BGEU branch on equality, we can use the
3863 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003864 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3865 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3866 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003867 return false;
3868 }
3869 // If we have a signed pseudo-branch and one of the registers is $0,
3870 // we can use an appropriate compare-to-zero branch. We select which one
3871 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003872 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3873 IsSrcRegZero ? TrgReg : SrcReg,
3874 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003875 return false;
3876 }
3877
3878 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3879 // expansions. If it is not available, we return.
3880 unsigned ATRegNum = getATReg(IDLoc);
3881 if (!ATRegNum)
3882 return true;
3883
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003884 if (!EmittedNoMacroWarning)
3885 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003886
3887 // SLT fits well with 2 of our 4 pseudo-branches:
3888 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3889 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3890 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3891 // This is accomplished by using a BNEZ with the result of the SLT.
3892 //
3893 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
Hiroshi Inoue7f9f92f2018-02-22 07:48:29 +00003894 // and BLE with BGT), so we change the BNEZ into a BEQZ.
Toma Tabacu1a108322015-06-17 13:20:24 +00003895 // Because only BGE and BLE branch on equality, we can use the
3896 // AcceptsEquality variable to decide when to emit the BEQZ.
3897 // Note that the order of the SLT arguments doesn't change between
3898 // opposites.
3899 //
3900 // The same applies to the unsigned variants, except that SLTu is used
3901 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003902 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3903 ReverseOrderSLT ? TrgReg : SrcReg,
3904 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003905
Daniel Sandersa736b372016-04-29 13:33:12 +00003906 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3907 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3908 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3909 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003910 return false;
3911}
3912
Simon Dardis509da1a2017-02-13 16:06:48 +00003913// Expand a integer division macro.
3914//
3915// Notably we don't have to emit a warning when encountering $rt as the $zero
3916// register, or 0 as an immediate. processInstruction() has already done that.
3917//
3918// The destination register can only be $zero when expanding (S)DivIMacro or
3919// D(S)DivMacro.
3920
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003921bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3922 const MCSubtargetInfo *STI, const bool IsMips64,
3923 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003924 MipsTargetStreamer &TOut = getTargetStreamer();
3925
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003926 warnIfNoMacro(IDLoc);
3927
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003928 const MCOperand &RdRegOp = Inst.getOperand(0);
3929 assert(RdRegOp.isReg() && "expected register operand kind");
3930 unsigned RdReg = RdRegOp.getReg();
3931
3932 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003933 assert(RsRegOp.isReg() && "expected register operand kind");
3934 unsigned RsReg = RsRegOp.getReg();
3935
Simon Dardis12850ee2017-01-31 10:49:24 +00003936 unsigned RtReg;
3937 int64_t ImmValue;
3938
3939 const MCOperand &RtOp = Inst.getOperand(2);
3940 assert((RtOp.isReg() || RtOp.isImm()) &&
3941 "expected register or immediate operand kind");
3942 if (RtOp.isReg())
3943 RtReg = RtOp.getReg();
3944 else
3945 ImmValue = RtOp.getImm();
3946
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003947 unsigned DivOp;
3948 unsigned ZeroReg;
Simon Dardis12850ee2017-01-31 10:49:24 +00003949 unsigned SubOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003950
3951 if (IsMips64) {
3952 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3953 ZeroReg = Mips::ZERO_64;
Simon Dardis12850ee2017-01-31 10:49:24 +00003954 SubOp = Mips::DSUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003955 } else {
3956 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3957 ZeroReg = Mips::ZERO;
Simon Dardis12850ee2017-01-31 10:49:24 +00003958 SubOp = Mips::SUB;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003959 }
3960
3961 bool UseTraps = useTraps();
3962
Simon Dardis12850ee2017-01-31 10:49:24 +00003963 if (RtOp.isImm()) {
3964 unsigned ATReg = getATReg(IDLoc);
3965 if (!ATReg)
3966 return true;
3967
3968 if (ImmValue == 0) {
Simon Dardis12850ee2017-01-31 10:49:24 +00003969 if (UseTraps)
3970 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
3971 else
3972 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
3973 return false;
3974 }
3975
3976 if (ImmValue == 1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003977 TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003978 return false;
3979 } else if (Signed && ImmValue == -1) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003980 TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
Simon Dardis12850ee2017-01-31 10:49:24 +00003981 return false;
3982 } else {
3983 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
3984 false, Inst.getLoc(), Out, STI))
3985 return true;
3986 TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
3987 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
3988 return false;
3989 }
3990 return true;
3991 }
3992
Simon Dardis509da1a2017-02-13 16:06:48 +00003993 // If the macro expansion of (d)div(u) would always trap or break, insert
3994 // the trap/break and exit. This gives a different result to GAS. GAS has
3995 // an inconsistency/missed optimization in that not all cases are handled
3996 // equivalently. As the observed behaviour is the same, we're ok.
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003997 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
Simon Dardis509da1a2017-02-13 16:06:48 +00003998 if (UseTraps) {
3999 TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004000 return false;
4001 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004002 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
4003 return false;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004004 }
4005
Simon Dardis509da1a2017-02-13 16:06:48 +00004006 // Temporary label for first branch traget
4007 MCContext &Context = TOut.getStreamer().getContext();
4008 MCSymbol *BrTarget;
4009 MCOperand LabelOp;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004010
4011 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004012 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004013 } else {
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004014 // Branch to the li instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004015 BrTarget = Context.createTempSymbol();
4016 LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4017 TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004018 }
4019
Daniel Sandersa736b372016-04-29 13:33:12 +00004020 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004021
4022 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004023 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004024
4025 if (!Signed) {
Simon Dardis509da1a2017-02-13 16:06:48 +00004026 if (!UseTraps)
4027 TOut.getStreamer().EmitLabel(BrTarget);
4028
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004029 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004030 return false;
4031 }
4032
4033 unsigned ATReg = getATReg(IDLoc);
4034 if (!ATReg)
4035 return true;
4036
Simon Dardis509da1a2017-02-13 16:06:48 +00004037 if (!UseTraps)
4038 TOut.getStreamer().EmitLabel(BrTarget);
4039
Daniel Sandersa736b372016-04-29 13:33:12 +00004040 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Simon Dardis509da1a2017-02-13 16:06:48 +00004041
4042 // Temporary label for the second branch target.
4043 MCSymbol *BrTargetEnd = Context.createTempSymbol();
4044 MCOperand LabelOpEnd =
4045 MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
4046
4047 // Branch to the mflo instruction.
4048 TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
4049
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004050 if (IsMips64) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004051 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
4052 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004053 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00004054 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004055 }
4056
4057 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00004058 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004059 else {
4060 // Branch to the mflo instruction.
Simon Dardis509da1a2017-02-13 16:06:48 +00004061 TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004062 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4063 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004064 }
Simon Dardis509da1a2017-02-13 16:06:48 +00004065
4066 TOut.getStreamer().EmitLabel(BrTargetEnd);
Zoran Jovanovic973405b2016-05-16 08:57:59 +00004067 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00004068 return false;
4069}
4070
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004071bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004072 SMLoc IDLoc, MCStreamer &Out,
4073 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004074 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004075
4076 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4077 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
4078 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
4079
4080 unsigned FirstReg = Inst.getOperand(0).getReg();
4081 unsigned SecondReg = Inst.getOperand(1).getReg();
4082 unsigned ThirdReg = Inst.getOperand(2).getReg();
4083
4084 if (hasMips1() && !hasMips2()) {
4085 unsigned ATReg = getATReg(IDLoc);
4086 if (!ATReg)
4087 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00004088 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4089 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
4090 TOut.emitNop(IDLoc, STI);
4091 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
4092 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
4093 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
4094 TOut.emitNop(IDLoc, STI);
4095 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
4096 : Mips::CVT_W_S,
4097 FirstReg, SecondReg, IDLoc, STI);
4098 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
4099 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004100 return false;
4101 }
4102
Daniel Sandersa736b372016-04-29 13:33:12 +00004103 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
4104 : Mips::TRUNC_W_S,
4105 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00004106
4107 return false;
4108}
4109
Daniel Sanders6394ee52015-10-15 14:52:58 +00004110bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004111 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00004112 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004113 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004114 }
4115
Toma Tabacud88d79c2015-06-23 14:39:42 +00004116 const MCOperand &DstRegOp = Inst.getOperand(0);
4117 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004118 const MCOperand &SrcRegOp = Inst.getOperand(1);
4119 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00004120 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4121 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4122
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004123 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00004124 unsigned DstReg = DstRegOp.getReg();
4125 unsigned SrcReg = SrcRegOp.getReg();
4126 int64_t OffsetValue = OffsetImmOp.getImm();
4127
4128 // NOTE: We always need AT for ULHU, as it is always used as the source
4129 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004130 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004131 unsigned ATReg = getATReg(IDLoc);
4132 if (!ATReg)
4133 return true;
4134
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004135 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4136 if (IsLargeOffset) {
4137 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4138 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00004139 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004140 }
4141
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004142 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
4143 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4144 if (isLittle())
4145 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004146
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004147 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
4148 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004149
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004150 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
4151 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00004152
Daniel Sandersa736b372016-04-29 13:33:12 +00004153 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004154 FirstOffset, IDLoc, STI);
4155 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004156 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00004157 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00004158
4159 return false;
4160}
4161
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004162bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004163 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004164 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00004165 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004166 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004167
4168 const MCOperand &DstRegOp = Inst.getOperand(0);
4169 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004170 const MCOperand &SrcRegOp = Inst.getOperand(1);
4171 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004172 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4173 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4174
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004175 MipsTargetStreamer &TOut = getTargetStreamer();
4176 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004177 unsigned SrcReg = SrcRegOp.getReg();
4178 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004179
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004180 warnIfNoMacro(IDLoc);
4181 unsigned ATReg = getATReg(IDLoc);
4182 if (!ATReg)
4183 return true;
4184
4185 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
4186 if (IsLargeOffset) {
4187 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
4188 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004189 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004190 }
4191
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004192 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
4193 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
4194 if (isLittle())
4195 std::swap(FirstOffset, SecondOffset);
4196
4197 if (IsLargeOffset) {
4198 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
4199 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
4200 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
4201 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
4202 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
4203 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004204 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004205 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
4206 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
4207 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004208 }
4209
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004210 return false;
4211}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004212
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00004213bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4214 const MCSubtargetInfo *STI) {
4215 if (hasMips32r6() || hasMips64r6()) {
4216 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
4217 }
4218
4219 const MCOperand &DstRegOp = Inst.getOperand(0);
4220 assert(DstRegOp.isReg() && "expected register operand kind");
4221 const MCOperand &SrcRegOp = Inst.getOperand(1);
4222 assert(SrcRegOp.isReg() && "expected register operand kind");
4223 const MCOperand &OffsetImmOp = Inst.getOperand(2);
4224 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
4225
4226 MipsTargetStreamer &TOut = getTargetStreamer();
4227 unsigned DstReg = DstRegOp.getReg();
4228 unsigned SrcReg = SrcRegOp.getReg();
4229 int64_t OffsetValue = OffsetImmOp.getImm();
4230
4231 // Compute left/right load/store offsets.
4232 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
4233 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
4234 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
4235 if (isLittle())
4236 std::swap(LxlOffset, LxrOffset);
4237
4238 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
4239 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
4240 unsigned TmpReg = SrcReg;
4241 if (IsLargeOffset || DoMove) {
4242 warnIfNoMacro(IDLoc);
4243 TmpReg = getATReg(IDLoc);
4244 if (!TmpReg)
4245 return true;
4246 }
4247
4248 if (IsLargeOffset) {
4249 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
4250 IDLoc, Out, STI))
4251 return true;
4252 }
4253
4254 if (DoMove)
4255 std::swap(DstReg, TmpReg);
4256
4257 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
4258 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
4259 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
4260 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
4261
4262 if (DoMove)
4263 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00004264
4265 return false;
4266}
4267
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004268bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004269 MCStreamer &Out,
4270 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004271 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004272
Eugene Zelenkodde94e42017-01-30 23:21:32 +00004273 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
4274 assert(Inst.getOperand(0).isReg() &&
4275 Inst.getOperand(1).isReg() &&
4276 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004277
4278 unsigned ATReg = Mips::NoRegister;
4279 unsigned FinalDstReg = Mips::NoRegister;
4280 unsigned DstReg = Inst.getOperand(0).getReg();
4281 unsigned SrcReg = Inst.getOperand(1).getReg();
4282 int64_t ImmValue = Inst.getOperand(2).getImm();
4283
Simon Dardisaa208812017-02-24 14:34:32 +00004284 bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004285
4286 unsigned FinalOpcode = Inst.getOpcode();
4287
4288 if (DstReg == SrcReg) {
4289 ATReg = getATReg(Inst.getLoc());
4290 if (!ATReg)
4291 return true;
4292 FinalDstReg = DstReg;
4293 DstReg = ATReg;
4294 }
4295
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004296 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004297 switch (FinalOpcode) {
4298 default:
4299 llvm_unreachable("unimplemented expansion");
Simon Dardisd410fc82017-02-23 12:40:58 +00004300 case Mips::ADDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004301 FinalOpcode = Mips::ADD;
4302 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004303 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004304 FinalOpcode = Mips::ADDu;
4305 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004306 case Mips::ANDi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004307 FinalOpcode = Mips::AND;
4308 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004309 case Mips::NORImm:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004310 FinalOpcode = Mips::NOR;
4311 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004312 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004313 FinalOpcode = Mips::OR;
4314 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004315 case Mips::SLTi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004316 FinalOpcode = Mips::SLT;
4317 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004318 case Mips::SLTiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004319 FinalOpcode = Mips::SLTu;
4320 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004321 case Mips::XORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004322 FinalOpcode = Mips::XOR;
4323 break;
Simon Dardisd410fc82017-02-23 12:40:58 +00004324 case Mips::ADDi_MM:
4325 FinalOpcode = Mips::ADD_MM;
4326 break;
4327 case Mips::ADDiu_MM:
4328 FinalOpcode = Mips::ADDu_MM;
4329 break;
4330 case Mips::ANDi_MM:
4331 FinalOpcode = Mips::AND_MM;
4332 break;
4333 case Mips::ORi_MM:
4334 FinalOpcode = Mips::OR_MM;
4335 break;
4336 case Mips::SLTi_MM:
4337 FinalOpcode = Mips::SLT_MM;
4338 break;
4339 case Mips::SLTiu_MM:
4340 FinalOpcode = Mips::SLTu_MM;
4341 break;
4342 case Mips::XORi_MM:
4343 FinalOpcode = Mips::XOR_MM;
4344 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004345 case Mips::ANDi64:
4346 FinalOpcode = Mips::AND64;
4347 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004348 case Mips::NORImm64:
4349 FinalOpcode = Mips::NOR64;
4350 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004351 case Mips::ORi64:
4352 FinalOpcode = Mips::OR64;
4353 break;
Simon Dardise3cceed2017-02-28 15:55:23 +00004354 case Mips::SLTImm64:
4355 FinalOpcode = Mips::SLT64;
4356 break;
4357 case Mips::SLTUImm64:
4358 FinalOpcode = Mips::SLTu64;
4359 break;
Simon Dardisaa208812017-02-24 14:34:32 +00004360 case Mips::XORi64:
4361 FinalOpcode = Mips::XOR64;
4362 break;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004363 }
4364
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004365 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00004366 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00004367 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004368 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00004369 return false;
4370 }
4371 return true;
4372}
4373
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004374bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4375 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004376 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004377 unsigned ATReg = Mips::NoRegister;
4378 unsigned DReg = Inst.getOperand(0).getReg();
4379 unsigned SReg = Inst.getOperand(1).getReg();
4380 unsigned TReg = Inst.getOperand(2).getReg();
4381 unsigned TmpReg = DReg;
4382
4383 unsigned FirstShift = Mips::NOP;
4384 unsigned SecondShift = Mips::NOP;
4385
4386 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004387 if (DReg == SReg) {
4388 TmpReg = getATReg(Inst.getLoc());
4389 if (!TmpReg)
4390 return true;
4391 }
4392
4393 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004394 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4395 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004396 return false;
4397 }
4398
4399 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004400 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004401 return false;
4402 }
4403
4404 return true;
4405 }
4406
4407 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004408 switch (Inst.getOpcode()) {
4409 default:
4410 llvm_unreachable("unexpected instruction opcode");
4411 case Mips::ROL:
4412 FirstShift = Mips::SRLV;
4413 SecondShift = Mips::SLLV;
4414 break;
4415 case Mips::ROR:
4416 FirstShift = Mips::SLLV;
4417 SecondShift = Mips::SRLV;
4418 break;
4419 }
4420
4421 ATReg = getATReg(Inst.getLoc());
4422 if (!ATReg)
4423 return true;
4424
Daniel Sandersa736b372016-04-29 13:33:12 +00004425 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4426 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4427 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4428 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004429
4430 return false;
4431 }
4432
4433 return true;
4434}
4435
4436bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004437 MCStreamer &Out,
4438 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004439 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004440 unsigned ATReg = Mips::NoRegister;
4441 unsigned DReg = Inst.getOperand(0).getReg();
4442 unsigned SReg = Inst.getOperand(1).getReg();
4443 int64_t ImmValue = Inst.getOperand(2).getImm();
4444
4445 unsigned FirstShift = Mips::NOP;
4446 unsigned SecondShift = Mips::NOP;
4447
4448 if (hasMips32r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004449 if (Inst.getOpcode() == Mips::ROLImm) {
4450 uint64_t MaxShift = 32;
4451 uint64_t ShiftValue = ImmValue;
4452 if (ImmValue != 0)
4453 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00004454 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004455 return false;
4456 }
4457
4458 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004459 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004460 return false;
4461 }
4462
4463 return true;
4464 }
4465
4466 if (hasMips32()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004467 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004468 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004469 return false;
4470 }
4471
4472 switch (Inst.getOpcode()) {
4473 default:
4474 llvm_unreachable("unexpected instruction opcode");
4475 case Mips::ROLImm:
4476 FirstShift = Mips::SLL;
4477 SecondShift = Mips::SRL;
4478 break;
4479 case Mips::RORImm:
4480 FirstShift = Mips::SRL;
4481 SecondShift = Mips::SLL;
4482 break;
4483 }
4484
4485 ATReg = getATReg(Inst.getLoc());
4486 if (!ATReg)
4487 return true;
4488
Daniel Sandersa736b372016-04-29 13:33:12 +00004489 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
4490 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
4491 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004492
4493 return false;
4494 }
4495
4496 return true;
4497}
4498
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004499bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4500 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004501 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004502 unsigned ATReg = Mips::NoRegister;
4503 unsigned DReg = Inst.getOperand(0).getReg();
4504 unsigned SReg = Inst.getOperand(1).getReg();
4505 unsigned TReg = Inst.getOperand(2).getReg();
4506 unsigned TmpReg = DReg;
4507
4508 unsigned FirstShift = Mips::NOP;
4509 unsigned SecondShift = Mips::NOP;
4510
4511 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004512 if (TmpReg == SReg) {
4513 TmpReg = getATReg(Inst.getLoc());
4514 if (!TmpReg)
4515 return true;
4516 }
4517
4518 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004519 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4520 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004521 return false;
4522 }
4523
4524 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004525 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004526 return false;
4527 }
4528
4529 return true;
4530 }
4531
4532 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004533 switch (Inst.getOpcode()) {
4534 default:
4535 llvm_unreachable("unexpected instruction opcode");
4536 case Mips::DROL:
4537 FirstShift = Mips::DSRLV;
4538 SecondShift = Mips::DSLLV;
4539 break;
4540 case Mips::DROR:
4541 FirstShift = Mips::DSLLV;
4542 SecondShift = Mips::DSRLV;
4543 break;
4544 }
4545
4546 ATReg = getATReg(Inst.getLoc());
4547 if (!ATReg)
4548 return true;
4549
Daniel Sandersa736b372016-04-29 13:33:12 +00004550 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
4551 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
4552 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
4553 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004554
4555 return false;
4556 }
4557
4558 return true;
4559}
4560
4561bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004562 MCStreamer &Out,
4563 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004564 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004565 unsigned ATReg = Mips::NoRegister;
4566 unsigned DReg = Inst.getOperand(0).getReg();
4567 unsigned SReg = Inst.getOperand(1).getReg();
4568 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
4569
4570 unsigned FirstShift = Mips::NOP;
4571 unsigned SecondShift = Mips::NOP;
4572
4573 MCInst TmpInst;
4574
4575 if (hasMips64r2()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004576 unsigned FinalOpcode = Mips::NOP;
4577 if (ImmValue == 0)
4578 FinalOpcode = Mips::DROTR;
4579 else if (ImmValue % 32 == 0)
4580 FinalOpcode = Mips::DROTR32;
4581 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
4582 if (Inst.getOpcode() == Mips::DROLImm)
4583 FinalOpcode = Mips::DROTR32;
4584 else
4585 FinalOpcode = Mips::DROTR;
4586 } else if (ImmValue >= 33) {
4587 if (Inst.getOpcode() == Mips::DROLImm)
4588 FinalOpcode = Mips::DROTR;
4589 else
4590 FinalOpcode = Mips::DROTR32;
4591 }
4592
4593 uint64_t ShiftValue = ImmValue % 32;
4594 if (Inst.getOpcode() == Mips::DROLImm)
4595 ShiftValue = (32 - ImmValue % 32) % 32;
4596
Daniel Sandersa736b372016-04-29 13:33:12 +00004597 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004598
4599 return false;
4600 }
4601
4602 if (hasMips64()) {
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004603 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004604 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004605 return false;
4606 }
4607
4608 switch (Inst.getOpcode()) {
4609 default:
4610 llvm_unreachable("unexpected instruction opcode");
4611 case Mips::DROLImm:
4612 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4613 FirstShift = Mips::DSLL;
4614 SecondShift = Mips::DSRL32;
4615 }
4616 if (ImmValue == 32) {
4617 FirstShift = Mips::DSLL32;
4618 SecondShift = Mips::DSRL32;
4619 }
4620 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4621 FirstShift = Mips::DSLL32;
4622 SecondShift = Mips::DSRL;
4623 }
4624 break;
4625 case Mips::DRORImm:
4626 if ((ImmValue >= 1) && (ImmValue <= 31)) {
4627 FirstShift = Mips::DSRL;
4628 SecondShift = Mips::DSLL32;
4629 }
4630 if (ImmValue == 32) {
4631 FirstShift = Mips::DSRL32;
4632 SecondShift = Mips::DSLL32;
4633 }
4634 if ((ImmValue >= 33) && (ImmValue <= 63)) {
4635 FirstShift = Mips::DSRL32;
4636 SecondShift = Mips::DSLL;
4637 }
4638 break;
4639 }
4640
4641 ATReg = getATReg(Inst.getLoc());
4642 if (!ATReg)
4643 return true;
4644
Daniel Sandersa736b372016-04-29 13:33:12 +00004645 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
4646 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
4647 Inst.getLoc(), STI);
4648 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00004649
4650 return false;
4651 }
4652
4653 return true;
4654}
4655
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004656bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4657 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00004658 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004659 unsigned FirstRegOp = Inst.getOperand(0).getReg();
4660 unsigned SecondRegOp = Inst.getOperand(1).getReg();
4661
Daniel Sandersa736b372016-04-29 13:33:12 +00004662 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004663 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00004664 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004665 else
Daniel Sandersa736b372016-04-29 13:33:12 +00004666 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
4667 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00004668
4669 return false;
4670}
4671
Simon Dardis3c82a642017-02-08 16:25:05 +00004672bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4673 const MCSubtargetInfo *STI) {
4674 MipsTargetStreamer &TOut = getTargetStreamer();
4675 unsigned ATReg = Mips::NoRegister;
4676 unsigned DstReg = Inst.getOperand(0).getReg();
4677 unsigned SrcReg = Inst.getOperand(1).getReg();
4678 int32_t ImmValue = Inst.getOperand(2).getImm();
4679
4680 ATReg = getATReg(IDLoc);
4681 if (!ATReg)
4682 return true;
4683
4684 loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
4685
4686 TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
4687 SrcReg, ATReg, IDLoc, STI);
4688
4689 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4690
4691 return false;
4692}
4693
4694bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4695 const MCSubtargetInfo *STI) {
4696 MipsTargetStreamer &TOut = getTargetStreamer();
4697 unsigned ATReg = Mips::NoRegister;
4698 unsigned DstReg = Inst.getOperand(0).getReg();
4699 unsigned SrcReg = Inst.getOperand(1).getReg();
4700 unsigned TmpReg = Inst.getOperand(2).getReg();
4701
4702 ATReg = getATReg(Inst.getLoc());
4703 if (!ATReg)
4704 return true;
4705
4706 TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
4707 SrcReg, TmpReg, IDLoc, STI);
4708
4709 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4710
4711 TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
4712 DstReg, DstReg, 0x1F, IDLoc, STI);
4713
4714 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4715
4716 if (useTraps()) {
4717 TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
4718 } else {
4719 MCContext & Context = TOut.getStreamer().getContext();
4720 MCSymbol * BrTarget = Context.createTempSymbol();
4721 MCOperand LabelOp =
4722 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4723
4724 TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
4725 if (AssemblerOptions.back()->isReorder())
4726 TOut.emitNop(IDLoc, STI);
4727 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4728
4729 TOut.getStreamer().EmitLabel(BrTarget);
4730 }
4731 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4732
4733 return false;
4734}
4735
4736bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4737 const MCSubtargetInfo *STI) {
4738 MipsTargetStreamer &TOut = getTargetStreamer();
4739 unsigned ATReg = Mips::NoRegister;
4740 unsigned DstReg = Inst.getOperand(0).getReg();
4741 unsigned SrcReg = Inst.getOperand(1).getReg();
4742 unsigned TmpReg = Inst.getOperand(2).getReg();
4743
4744 ATReg = getATReg(IDLoc);
4745 if (!ATReg)
4746 return true;
4747
4748 TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
4749 SrcReg, TmpReg, IDLoc, STI);
4750
4751 TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
4752 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4753 if (useTraps()) {
4754 TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
4755 } else {
4756 MCContext & Context = TOut.getStreamer().getContext();
4757 MCSymbol * BrTarget = Context.createTempSymbol();
4758 MCOperand LabelOp =
4759 MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
4760
4761 TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
4762 if (AssemblerOptions.back()->isReorder())
4763 TOut.emitNop(IDLoc, STI);
4764 TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
4765
4766 TOut.getStreamer().EmitLabel(BrTarget);
4767 }
4768
4769 return false;
4770}
4771
4772bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4773 const MCSubtargetInfo *STI) {
4774 MipsTargetStreamer &TOut = getTargetStreamer();
4775 unsigned DstReg = Inst.getOperand(0).getReg();
4776 unsigned SrcReg = Inst.getOperand(1).getReg();
4777 unsigned TmpReg = Inst.getOperand(2).getReg();
4778
4779 TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
4780 TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
4781
4782 return false;
4783}
4784
Simon Dardisaff4d142016-10-18 14:28:00 +00004785// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
4786// lw $<reg+1>>, offset+4($reg2)'
4787// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
4788// sw $<reg+1>>, offset+4($reg2)'
4789// for O32.
4790bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
4791 MCStreamer &Out,
4792 const MCSubtargetInfo *STI,
4793 bool IsLoad) {
4794 if (!isABI_O32())
4795 return true;
4796
4797 warnIfNoMacro(IDLoc);
4798
4799 MipsTargetStreamer &TOut = getTargetStreamer();
4800 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
4801 unsigned FirstReg = Inst.getOperand(0).getReg();
4802 unsigned SecondReg = nextReg(FirstReg);
4803 unsigned BaseReg = Inst.getOperand(1).getReg();
4804 if (!SecondReg)
4805 return true;
4806
4807 warnIfRegIndexIsAT(FirstReg, IDLoc);
4808
4809 assert(Inst.getOperand(2).isImm() &&
4810 "Offset for load macro is not immediate!");
4811
4812 MCOperand &FirstOffset = Inst.getOperand(2);
4813 signed NextOffset = FirstOffset.getImm() + 4;
4814 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
4815
4816 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
4817 return true;
4818
4819 // For loads, clobber the base register with the second load instead of the
4820 // first if the BaseReg == FirstReg.
4821 if (FirstReg != BaseReg || !IsLoad) {
4822 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4823 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4824 } else {
4825 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
4826 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
4827 }
4828
4829 return false;
4830}
4831
Simon Dardis43115a12016-11-21 20:30:41 +00004832bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4833 const MCSubtargetInfo *STI) {
4834
4835 warnIfNoMacro(IDLoc);
4836 MipsTargetStreamer &TOut = getTargetStreamer();
4837
4838 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
4839 Inst.getOperand(2).getReg() != Mips::ZERO) {
4840 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4841 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
4842 IDLoc, STI);
4843 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4844 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4845 return false;
4846 }
4847
4848 unsigned Reg = 0;
4849 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
4850 Reg = Inst.getOperand(2).getReg();
4851 } else {
4852 Reg = Inst.getOperand(1).getReg();
4853 }
4854 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
4855 return false;
4856}
4857
4858bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4859 const MCSubtargetInfo *STI) {
Simon Dardis43115a12016-11-21 20:30:41 +00004860 warnIfNoMacro(IDLoc);
4861 MipsTargetStreamer &TOut = getTargetStreamer();
4862
4863 unsigned Opc;
4864 int64_t Imm = Inst.getOperand(2).getImm();
4865 unsigned Reg = Inst.getOperand(1).getReg();
4866
4867 if (Imm == 0) {
4868 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4869 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
4870 return false;
4871 } else {
4872
4873 if (Reg == Mips::ZERO) {
4874 Warning(IDLoc, "comparison is always false");
4875 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4876 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4877 return false;
4878 }
4879
4880 if (Imm > -0x8000 && Imm < 0) {
4881 Imm = -Imm;
4882 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4883 } else {
4884 Opc = Mips::XORi;
4885 }
4886 }
4887 if (!isUInt<16>(Imm)) {
4888 unsigned ATReg = getATReg(IDLoc);
4889 if (!ATReg)
4890 return true;
4891
4892 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4893 Out, STI))
4894 return true;
4895
4896 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4897 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4898 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4899 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4900 return false;
4901 }
4902
4903 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4904 Imm, IDLoc, STI);
4905 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4906 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4907 return false;
4908}
4909
Simon Dardisde5ed0c2017-11-14 22:26:42 +00004910// Map the DSP accumulator and control register to the corresponding gpr
4911// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
4912// do not map the DSP registers contigously to gpr registers.
4913static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
4914 switch (Inst.getOpcode()) {
4915 case Mips::MFTLO:
4916 case Mips::MTTLO:
4917 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4918 case Mips::AC0:
4919 return Mips::ZERO;
4920 case Mips::AC1:
4921 return Mips::A0;
4922 case Mips::AC2:
4923 return Mips::T0;
4924 case Mips::AC3:
4925 return Mips::T4;
4926 default:
4927 llvm_unreachable("Unknown register for 'mttr' alias!");
4928 }
4929 case Mips::MFTHI:
4930 case Mips::MTTHI:
4931 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4932 case Mips::AC0:
4933 return Mips::AT;
4934 case Mips::AC1:
4935 return Mips::A1;
4936 case Mips::AC2:
4937 return Mips::T1;
4938 case Mips::AC3:
4939 return Mips::T5;
4940 default:
4941 llvm_unreachable("Unknown register for 'mttr' alias!");
4942 }
4943 case Mips::MFTACX:
4944 case Mips::MTTACX:
4945 switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
4946 case Mips::AC0:
4947 return Mips::V0;
4948 case Mips::AC1:
4949 return Mips::A2;
4950 case Mips::AC2:
4951 return Mips::T2;
4952 case Mips::AC3:
4953 return Mips::T6;
4954 default:
4955 llvm_unreachable("Unknown register for 'mttr' alias!");
4956 }
4957 case Mips::MFTDSP:
4958 case Mips::MTTDSP:
4959 return Mips::S0;
4960 default:
4961 llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
4962 }
4963}
4964
4965// Map the floating point register operand to the corresponding register
4966// operand.
4967static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
4968 switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
4969 case Mips::F0: return Mips::ZERO;
4970 case Mips::F1: return Mips::AT;
4971 case Mips::F2: return Mips::V0;
4972 case Mips::F3: return Mips::V1;
4973 case Mips::F4: return Mips::A0;
4974 case Mips::F5: return Mips::A1;
4975 case Mips::F6: return Mips::A2;
4976 case Mips::F7: return Mips::A3;
4977 case Mips::F8: return Mips::T0;
4978 case Mips::F9: return Mips::T1;
4979 case Mips::F10: return Mips::T2;
4980 case Mips::F11: return Mips::T3;
4981 case Mips::F12: return Mips::T4;
4982 case Mips::F13: return Mips::T5;
4983 case Mips::F14: return Mips::T6;
4984 case Mips::F15: return Mips::T7;
4985 case Mips::F16: return Mips::S0;
4986 case Mips::F17: return Mips::S1;
4987 case Mips::F18: return Mips::S2;
4988 case Mips::F19: return Mips::S3;
4989 case Mips::F20: return Mips::S4;
4990 case Mips::F21: return Mips::S5;
4991 case Mips::F22: return Mips::S6;
4992 case Mips::F23: return Mips::S7;
4993 case Mips::F24: return Mips::T8;
4994 case Mips::F25: return Mips::T9;
4995 case Mips::F26: return Mips::K0;
4996 case Mips::F27: return Mips::K1;
4997 case Mips::F28: return Mips::GP;
4998 case Mips::F29: return Mips::SP;
4999 case Mips::F30: return Mips::FP;
5000 case Mips::F31: return Mips::RA;
5001 default: llvm_unreachable("Unknown register for mttc1 alias!");
5002 }
5003}
5004
5005// Map the coprocessor operand the corresponding gpr register operand.
5006static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
5007 switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
5008 case Mips::COP00: return Mips::ZERO;
5009 case Mips::COP01: return Mips::AT;
5010 case Mips::COP02: return Mips::V0;
5011 case Mips::COP03: return Mips::V1;
5012 case Mips::COP04: return Mips::A0;
5013 case Mips::COP05: return Mips::A1;
5014 case Mips::COP06: return Mips::A2;
5015 case Mips::COP07: return Mips::A3;
5016 case Mips::COP08: return Mips::T0;
5017 case Mips::COP09: return Mips::T1;
5018 case Mips::COP010: return Mips::T2;
5019 case Mips::COP011: return Mips::T3;
5020 case Mips::COP012: return Mips::T4;
5021 case Mips::COP013: return Mips::T5;
5022 case Mips::COP014: return Mips::T6;
5023 case Mips::COP015: return Mips::T7;
5024 case Mips::COP016: return Mips::S0;
5025 case Mips::COP017: return Mips::S1;
5026 case Mips::COP018: return Mips::S2;
5027 case Mips::COP019: return Mips::S3;
5028 case Mips::COP020: return Mips::S4;
5029 case Mips::COP021: return Mips::S5;
5030 case Mips::COP022: return Mips::S6;
5031 case Mips::COP023: return Mips::S7;
5032 case Mips::COP024: return Mips::T8;
5033 case Mips::COP025: return Mips::T9;
5034 case Mips::COP026: return Mips::K0;
5035 case Mips::COP027: return Mips::K1;
5036 case Mips::COP028: return Mips::GP;
5037 case Mips::COP029: return Mips::SP;
5038 case Mips::COP030: return Mips::FP;
5039 case Mips::COP031: return Mips::RA;
5040 default: llvm_unreachable("Unknown register for mttc0 alias!");
5041 }
5042}
5043
5044/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
5045/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
5046bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5047 const MCSubtargetInfo *STI) {
5048 MipsTargetStreamer &TOut = getTargetStreamer();
5049 unsigned rd = 0;
5050 unsigned u = 1;
5051 unsigned sel = 0;
5052 unsigned h = 0;
5053 bool IsMFTR = false;
5054 switch (Inst.getOpcode()) {
5055 case Mips::MFTC0:
5056 IsMFTR = true;
5057 LLVM_FALLTHROUGH;
5058 case Mips::MTTC0:
5059 u = 0;
5060 rd = getRegisterForMxtrC0(Inst, IsMFTR);
5061 sel = Inst.getOperand(2).getImm();
5062 break;
5063 case Mips::MFTGPR:
5064 IsMFTR = true;
5065 LLVM_FALLTHROUGH;
5066 case Mips::MTTGPR:
5067 rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
5068 break;
5069 case Mips::MFTLO:
5070 case Mips::MFTHI:
5071 case Mips::MFTACX:
5072 case Mips::MFTDSP:
5073 IsMFTR = true;
5074 LLVM_FALLTHROUGH;
5075 case Mips::MTTLO:
5076 case Mips::MTTHI:
5077 case Mips::MTTACX:
5078 case Mips::MTTDSP:
5079 rd = getRegisterForMxtrDSP(Inst, IsMFTR);
5080 sel = 1;
5081 break;
5082 case Mips::MFTHC1:
5083 h = 1;
5084 LLVM_FALLTHROUGH;
5085 case Mips::MFTC1:
5086 IsMFTR = true;
5087 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5088 sel = 2;
5089 break;
5090 case Mips::MTTHC1:
5091 h = 1;
5092 LLVM_FALLTHROUGH;
5093 case Mips::MTTC1:
5094 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5095 sel = 2;
5096 break;
5097 case Mips::CFTC1:
5098 IsMFTR = true;
5099 LLVM_FALLTHROUGH;
5100 case Mips::CTTC1:
5101 rd = getRegisterForMxtrFP(Inst, IsMFTR);
5102 sel = 3;
5103 break;
5104 }
5105 unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
5106 unsigned Op1 =
5107 IsMFTR ? rd
5108 : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
5109 : Inst.getOperand(0).getReg());
5110
5111 TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
5112 STI);
5113 return false;
5114}
5115
Daniel Sandersc5537422016-07-27 13:49:44 +00005116unsigned
5117MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
5118 const OperandVector &Operands) {
5119 switch (Inst.getOpcode()) {
5120 default:
5121 return Match_Success;
5122 case Mips::DATI:
5123 case Mips::DAHI:
Daniel Sandersb23005e2016-07-28 15:59:06 +00005124 if (static_cast<MipsOperand &>(*Operands[1])
5125 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
5126 return Match_Success;
5127 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00005128 }
5129}
Simon Dardis730fdb72017-01-16 13:55:58 +00005130
Matheus Almeida595fcab2014-06-11 15:05:56 +00005131unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00005132 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00005133 // As described by the MIPSR6 spec, daui must not use the zero operand for
5134 // its source operand.
5135 case Mips::DAUI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00005136 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5137 Inst.getOperand(1).getReg() == Mips::ZERO_64)
5138 return Match_RequiresNoZeroRegister;
5139 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00005140 // As described by the Mips32r2 spec, the registers Rd and Rs for
5141 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00005142 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00005143 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00005144 case Mips::JALR_HB:
Simon Dardis7bc8ad52018-02-21 00:06:53 +00005145 case Mips::JALR_HB64:
Simon Dardisb60833c2016-05-31 17:34:42 +00005146 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00005147 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00005148 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5149 return Match_RequiresDifferentSrcAndDst;
5150 return Match_Success;
5151 case Mips::LWP_MM:
5152 case Mips::LWP_MMR6:
5153 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
5154 return Match_RequiresDifferentSrcAndDst;
5155 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00005156 case Mips::SYNC:
5157 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
5158 return Match_NonZeroOperandForSync;
5159 return Match_Success;
Simon Dardis52ae4f02018-03-07 11:39:48 +00005160 case Mips::MFC0:
5161 case Mips::MTC0:
5162 case Mips::MTC2:
5163 case Mips::MFC2:
5164 if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
5165 return Match_NonZeroOperandForMTCX;
5166 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005167 // As described the MIPSR6 spec, the compact branches that compare registers
5168 // must:
5169 // a) Not use the zero register.
5170 // b) Not use the same register twice.
5171 // c) rs < rt for bnec, beqc.
5172 // NB: For this case, the encoding will swap the operands as their
5173 // ordering doesn't matter. GAS performs this transformation too.
5174 // Hence, that constraint does not have to be enforced.
5175 //
5176 // The compact branches that branch iff the signed addition of two registers
5177 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
5178 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005179 case Mips::BLEZC: case Mips::BLEZC_MMR6:
5180 case Mips::BGEZC: case Mips::BGEZC_MMR6:
5181 case Mips::BGTZC: case Mips::BGTZC_MMR6:
5182 case Mips::BLTZC: case Mips::BLTZC_MMR6:
5183 case Mips::BEQZC: case Mips::BEQZC_MMR6:
5184 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005185 case Mips::BLEZC64:
5186 case Mips::BGEZC64:
5187 case Mips::BGTZC64:
5188 case Mips::BLTZC64:
5189 case Mips::BEQZC64:
5190 case Mips::BNEZC64:
5191 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5192 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005193 return Match_RequiresNoZeroRegister;
5194 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00005195 case Mips::BGEC: case Mips::BGEC_MMR6:
5196 case Mips::BLTC: case Mips::BLTC_MMR6:
5197 case Mips::BGEUC: case Mips::BGEUC_MMR6:
5198 case Mips::BLTUC: case Mips::BLTUC_MMR6:
5199 case Mips::BEQC: case Mips::BEQC_MMR6:
5200 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00005201 case Mips::BGEC64:
5202 case Mips::BLTC64:
5203 case Mips::BGEUC64:
5204 case Mips::BLTUC64:
5205 case Mips::BEQC64:
5206 case Mips::BNEC64:
5207 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
5208 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005209 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00005210 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
5211 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00005212 return Match_RequiresNoZeroRegister;
5213 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
5214 return Match_RequiresDifferentOperands;
5215 return Match_Success;
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005216 case Mips::DINS: {
Simon Dardis55e44672017-09-14 17:27:53 +00005217 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5218 "Operands must be immediates for dins!");
5219 const signed Pos = Inst.getOperand(2).getImm();
5220 const signed Size = Inst.getOperand(3).getImm();
5221 if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
5222 return Match_RequiresPosSizeRange0_32;
5223 return Match_Success;
5224 }
5225 case Mips::DINSM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005226 case Mips::DINSU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005227 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5228 "Operands must be immediates for dinsm/dinsu!");
5229 const signed Pos = Inst.getOperand(2).getImm();
5230 const signed Size = Inst.getOperand(3).getImm();
5231 if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
5232 return Match_RequiresPosSizeRange33_64;
5233 return Match_Success;
5234 }
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005235 case Mips::DEXT: {
Simon Dardis55e44672017-09-14 17:27:53 +00005236 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5237 "Operands must be immediates for DEXTM!");
5238 const signed Pos = Inst.getOperand(2).getImm();
5239 const signed Size = Inst.getOperand(3).getImm();
5240 if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
5241 return Match_RequiresPosSizeUImm6;
5242 return Match_Success;
5243 }
5244 case Mips::DEXTM:
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00005245 case Mips::DEXTU: {
Simon Dardis55e44672017-09-14 17:27:53 +00005246 assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
5247 "Operands must be immediates for dextm/dextu!");
5248 const signed Pos = Inst.getOperand(2).getImm();
5249 const signed Size = Inst.getOperand(3).getImm();
5250 if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
5251 return Match_RequiresPosSizeRange33_64;
5252 return Match_Success;
5253 }
Petar Jovanovic3408caf2018-03-14 14:13:31 +00005254 case Mips::CRC32B: case Mips::CRC32CB:
5255 case Mips::CRC32H: case Mips::CRC32CH:
5256 case Mips::CRC32W: case Mips::CRC32CW:
5257 case Mips::CRC32D: case Mips::CRC32CD:
5258 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
5259 return Match_RequiresSameSrcAndDst;
5260 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00005261 }
Simon Dardis730fdb72017-01-16 13:55:58 +00005262
5263 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
5264 if ((TSFlags & MipsII::HasFCCRegOperand) &&
5265 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
5266 return Match_NoFCCRegisterForCurrentISA;
5267
5268 return Match_Success;
5269
Matheus Almeida595fcab2014-06-11 15:05:56 +00005270}
5271
Daniel Sanders52da7af2015-11-06 12:11:03 +00005272static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
5273 uint64_t ErrorInfo) {
5274 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
5275 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
5276 if (ErrorLoc == SMLoc())
5277 return Loc;
5278 return ErrorLoc;
5279 }
5280 return Loc;
5281}
5282
David Blaikie960ea3f2014-06-08 16:18:35 +00005283bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
5284 OperandVector &Operands,
5285 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00005286 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00005287 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005288 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00005289 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00005290 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00005291
5292 switch (MatchResult) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00005293 case Match_Success:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005294 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00005295 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005296 return false;
Jack Carterb4dbc172012-09-05 23:34:03 +00005297 case Match_MissingFeature:
5298 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5299 return true;
5300 case Match_InvalidOperand: {
5301 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00005302 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005303 if (ErrorInfo >= Operands.size())
5304 return Error(IDLoc, "too few operands for instruction");
5305
Daniel Sanders52da7af2015-11-06 12:11:03 +00005306 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005307 if (ErrorLoc == SMLoc())
5308 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00005309 }
5310
5311 return Error(ErrorLoc, "invalid operand for instruction");
5312 }
Simon Dardisc4463c92016-10-18 14:42:13 +00005313 case Match_NonZeroOperandForSync:
5314 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Simon Dardis52ae4f02018-03-07 11:39:48 +00005315 case Match_NonZeroOperandForMTCX:
5316 return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00005317 case Match_MnemonicFail:
5318 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00005319 case Match_RequiresDifferentSrcAndDst:
5320 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00005321 case Match_RequiresDifferentOperands:
5322 return Error(IDLoc, "registers must be different");
5323 case Match_RequiresNoZeroRegister:
5324 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00005325 case Match_RequiresSameSrcAndDst:
5326 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00005327 case Match_NoFCCRegisterForCurrentISA:
5328 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5329 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00005330 case Match_Immz:
5331 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005332 case Match_UImm1_0:
5333 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5334 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00005335 case Match_UImm2_0:
5336 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5337 "expected 2-bit unsigned immediate");
5338 case Match_UImm2_1:
5339 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5340 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00005341 case Match_UImm3_0:
5342 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5343 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00005344 case Match_UImm4_0:
5345 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5346 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00005347 case Match_SImm4_0:
5348 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5349 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005350 case Match_UImm5_0:
5351 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5352 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00005353 case Match_SImm5_0:
5354 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5355 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005356 case Match_UImm5_1:
5357 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5358 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005359 case Match_UImm5_32:
5360 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5361 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00005362 case Match_UImm5_33:
5363 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5364 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00005365 case Match_UImm5_0_Report_UImm6:
5366 // This is used on UImm5 operands that have a corresponding UImm5_32
5367 // operand to avoid confusing the user.
5368 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5369 "expected 6-bit unsigned immediate");
5370 case Match_UImm5_Lsl2:
5371 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5372 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00005373 case Match_UImmRange2_64:
5374 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5375 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00005376 case Match_UImm6_0:
5377 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5378 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00005379 case Match_UImm6_Lsl2:
5380 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5381 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00005382 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00005383 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5384 "expected 6-bit signed immediate");
5385 case Match_UImm7_0:
5386 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5387 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00005388 case Match_UImm7_N1:
5389 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5390 "expected immediate in range -1 .. 126");
5391 case Match_SImm7_Lsl2:
5392 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5393 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00005394 case Match_UImm8_0:
5395 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5396 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00005397 case Match_UImm10_0:
5398 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5399 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00005400 case Match_SImm10_0:
5401 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5402 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00005403 case Match_SImm11_0:
5404 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5405 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005406 case Match_UImm16:
5407 case Match_UImm16_Relaxed:
Petar Jovanovice4dacb72017-09-12 21:43:33 +00005408 case Match_UImm16_AltRelaxed:
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00005409 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5410 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005411 case Match_SImm16:
5412 case Match_SImm16_Relaxed:
5413 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5414 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00005415 case Match_SImm19_Lsl2:
5416 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5417 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00005418 case Match_UImm20_0:
5419 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5420 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00005421 case Match_UImm26_0:
5422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5423 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00005424 case Match_SImm32:
5425 case Match_SImm32_Relaxed:
5426 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5427 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00005428 case Match_UImm32_Coerced:
5429 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5430 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00005431 case Match_MemSImm9:
5432 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5433 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00005434 case Match_MemSImm10:
5435 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5436 "expected memory with 10-bit signed offset");
5437 case Match_MemSImm10Lsl1:
5438 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5439 "expected memory with 11-bit signed offset and multiple of 2");
5440 case Match_MemSImm10Lsl2:
5441 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5442 "expected memory with 12-bit signed offset and multiple of 4");
5443 case Match_MemSImm10Lsl3:
5444 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5445 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00005446 case Match_MemSImm11:
5447 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5448 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00005449 case Match_MemSImm12:
5450 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5451 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00005452 case Match_MemSImm16:
5453 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
5454 "expected memory with 16-bit signed offset");
Simon Dardis6f83ae32017-09-14 15:17:50 +00005455 case Match_RequiresPosSizeRange0_32: {
5456 SMLoc ErrorStart = Operands[3]->getStartLoc();
5457 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5458 return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
5459 SMRange(ErrorStart, ErrorEnd));
5460 }
Simon Dardis55e44672017-09-14 17:27:53 +00005461 case Match_RequiresPosSizeUImm6: {
5462 SMLoc ErrorStart = Operands[3]->getStartLoc();
5463 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5464 return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
5465 SMRange(ErrorStart, ErrorEnd));
5466 }
Simon Dardis6f83ae32017-09-14 15:17:50 +00005467 case Match_RequiresPosSizeRange33_64: {
5468 SMLoc ErrorStart = Operands[3]->getStartLoc();
5469 SMLoc ErrorEnd = Operands[4]->getEndLoc();
5470 return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
5471 SMRange(ErrorStart, ErrorEnd));
5472 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005473 }
Craig Topper589ceee2015-01-03 08:16:34 +00005474
5475 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00005476}
5477
Toma Tabacud9d344b2015-04-27 14:05:04 +00005478void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
5479 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
5480 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
5481 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00005482}
5483
Toma Tabacu81496c12015-05-20 08:54:45 +00005484void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
5485 if (!AssemblerOptions.back()->isMacro())
5486 Warning(Loc, "macro instruction expanded into multiple instructions");
5487}
5488
Daniel Sandersef638fe2014-10-03 15:37:37 +00005489void
5490MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
5491 SMRange Range, bool ShowColors) {
5492 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00005493 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00005494 ShowColors);
5495}
5496
Jack Carter1ac53222013-02-20 23:11:17 +00005497int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005498 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005499
Vladimir Medic4c299852013-11-06 11:27:05 +00005500 CC = StringSwitch<unsigned>(Name)
5501 .Case("zero", 0)
Petar Jovanovic636851b2017-06-22 15:24:16 +00005502 .Cases("at", "AT", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00005503 .Case("a0", 4)
5504 .Case("a1", 5)
5505 .Case("a2", 6)
5506 .Case("a3", 7)
5507 .Case("v0", 2)
5508 .Case("v1", 3)
5509 .Case("s0", 16)
5510 .Case("s1", 17)
5511 .Case("s2", 18)
5512 .Case("s3", 19)
5513 .Case("s4", 20)
5514 .Case("s5", 21)
5515 .Case("s6", 22)
5516 .Case("s7", 23)
5517 .Case("k0", 26)
5518 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005519 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00005520 .Case("sp", 29)
5521 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00005522 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00005523 .Case("ra", 31)
5524 .Case("t0", 8)
5525 .Case("t1", 9)
5526 .Case("t2", 10)
5527 .Case("t3", 11)
5528 .Case("t4", 12)
5529 .Case("t5", 13)
5530 .Case("t6", 14)
5531 .Case("t7", 15)
5532 .Case("t8", 24)
5533 .Case("t9", 25)
5534 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005535
Toma Tabacufda445c2014-09-15 15:33:01 +00005536 if (!(isABI_N32() || isABI_N64()))
5537 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00005538
Daniel Sandersef638fe2014-10-03 15:37:37 +00005539 if (12 <= CC && CC <= 15) {
5540 // Name is one of t4-t7
5541 AsmToken RegTok = getLexer().peekTok();
5542 SMRange RegRange = RegTok.getLocRange();
5543
5544 StringRef FixedName = StringSwitch<StringRef>(Name)
5545 .Case("t4", "t0")
5546 .Case("t5", "t1")
5547 .Case("t6", "t2")
5548 .Case("t7", "t3")
5549 .Default("");
5550 assert(FixedName != "" && "Register name is not one of t4-t7.");
5551
5552 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
5553 "Did you mean $" + FixedName + "?", RegRange);
5554 }
5555
Toma Tabacufda445c2014-09-15 15:33:01 +00005556 // Although SGI documentation just cuts out t0-t3 for n32/n64,
5557 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
5558 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
5559 if (8 <= CC && CC <= 11)
5560 CC += 4;
5561
5562 if (CC == -1)
5563 CC = StringSwitch<unsigned>(Name)
5564 .Case("a4", 8)
5565 .Case("a5", 9)
5566 .Case("a6", 10)
5567 .Case("a7", 11)
5568 .Case("kt0", 26)
5569 .Case("kt1", 27)
5570 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00005571
5572 return CC;
5573}
Jack Carterd0bd6422013-04-18 00:41:53 +00005574
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005575int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
5576 int CC;
5577
5578 CC = StringSwitch<unsigned>(Name)
5579 .Case("hwr_cpunum", 0)
5580 .Case("hwr_synci_step", 1)
5581 .Case("hwr_cc", 2)
5582 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00005583 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005584 .Default(-1);
5585
5586 return CC;
5587}
5588
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005589int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Cartera63b16a2012-09-07 00:23:42 +00005590 if (Name[0] == 'f') {
5591 StringRef NumString = Name.substr(1);
5592 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00005593 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005594 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005595 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00005596 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005597 return IntVal;
5598 }
5599 return -1;
5600}
Jack Cartera63b16a2012-09-07 00:23:42 +00005601
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005602int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005603 if (Name.startswith("fcc")) {
5604 StringRef NumString = Name.substr(3);
5605 unsigned IntVal;
5606 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005607 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005608 if (IntVal > 7) // There are only 8 fcc registers.
5609 return -1;
5610 return IntVal;
5611 }
5612 return -1;
5613}
5614
5615int MipsAsmParser::matchACRegisterName(StringRef Name) {
Akira Hatanaka274d24c2013-08-14 01:15:52 +00005616 if (Name.startswith("ac")) {
5617 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005618 unsigned IntVal;
5619 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00005620 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005621 if (IntVal > 3) // There are only 3 acc registers.
5622 return -1;
5623 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00005624 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005625 return -1;
5626}
Jack Carterd0bd6422013-04-18 00:41:53 +00005627
Jack Carter5dc8ac92013-09-25 23:50:44 +00005628int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
5629 unsigned IntVal;
5630
5631 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
5632 return -1;
5633
5634 if (IntVal > 31)
5635 return -1;
5636
5637 return IntVal;
5638}
5639
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005640int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
5641 int CC;
5642
5643 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00005644 .Case("msair", 0)
5645 .Case("msacsr", 1)
5646 .Case("msaaccess", 2)
5647 .Case("msasave", 3)
5648 .Case("msamodify", 4)
5649 .Case("msarequest", 5)
5650 .Case("msamap", 6)
5651 .Case("msaunmap", 7)
5652 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00005653
5654 return CC;
5655}
5656
Simon Dardis3aa8a902017-02-06 12:43:46 +00005657bool MipsAsmParser::canUseATReg() {
5658 return AssemblerOptions.back()->getATRegIndex() != 0;
5659}
5660
Toma Tabacu89a712b2015-04-15 10:48:56 +00005661unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00005662 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00005663 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00005664 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00005665 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00005666 return 0;
5667 }
5668 unsigned AT = getReg(
5669 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00005670 return AT;
5671}
Jack Carter0b744b32012-10-04 02:29:46 +00005672
Jack Carterd0bd6422013-04-18 00:41:53 +00005673unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00005674 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00005675}
5676
Toma Tabacu13964452014-09-04 13:23:44 +00005677bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005678 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00005679 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005680
Jack Carter30a59822012-10-04 04:03:53 +00005681 // Check if the current operand has a custom associated parser, if so, try to
5682 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00005683 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
5684 if (ResTy == MatchOperand_Success)
5685 return false;
5686 // If there wasn't a custom match, try the generic matcher below. Otherwise,
5687 // there was a match, but an error occurred, in which case, just return that
5688 // the operand parsing failed.
5689 if (ResTy == MatchOperand_ParseFail)
5690 return true;
5691
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005692 DEBUG(dbgs() << ".. Generic Parser\n");
5693
Jack Carterb4dbc172012-09-05 23:34:03 +00005694 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005695 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00005696 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00005697 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005698
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005699 // Almost all registers have been parsed by custom parsers. There is only
5700 // one exception to this. $zero (and it's alias $0) will reach this point
5701 // for div, divu, and similar instructions because it is not an operand
5702 // to the instruction definition but an explicit register. Special case
5703 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00005704 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00005705 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005706
Jack Carterd0bd6422013-04-18 00:41:53 +00005707 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00005708 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005709 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00005710 return true;
5711
Jack Carter873c7242013-01-12 01:03:14 +00005712 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00005713 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00005714 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00005715 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00005716 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00005717
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005718 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005719 return false;
5720 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005721 default: {
5722 DEBUG(dbgs() << ".. generic integer expression\n");
5723
5724 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00005725 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005726 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00005727 return true;
5728
Jack Carter873c7242013-01-12 01:03:14 +00005729 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5730
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005731 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00005732 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005733 }
Jack Carter0b744b32012-10-04 02:29:46 +00005734 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00005735 return true;
5736}
5737
Jack Carterb5cf5902013-04-17 00:18:04 +00005738bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00005739 switch (Expr->getKind()) {
5740 case MCExpr::Constant:
5741 return true;
5742 case MCExpr::SymbolRef:
5743 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
Simon Dardisc6be2252017-08-09 10:47:52 +00005744 case MCExpr::Binary: {
Simon Dardis02c9a3d2017-08-18 13:27:02 +00005745 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
Simon Dardisc6be2252017-08-09 10:47:52 +00005746 if (!isEvaluated(BE->getLHS()))
5747 return false;
5748 return isEvaluated(BE->getRHS());
5749 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005750 case MCExpr::Unary:
5751 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00005752 case MCExpr::Target:
5753 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005754 }
Jack Carterb5cf5902013-04-17 00:18:04 +00005755 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00005756}
Jack Carterd0bd6422013-04-18 00:41:53 +00005757
Jack Carterb4dbc172012-09-05 23:34:03 +00005758bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
5759 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005760 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00005761 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005762 if (ResTy == MatchOperand_Success) {
5763 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00005764 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005765 StartLoc = Operand.getStartLoc();
5766 EndLoc = Operand.getEndLoc();
5767
5768 // AFAIK, we only support numeric registers and named GPR's in CFI
5769 // directives.
5770 // Don't worry about eating tokens before failing. Using an unrecognised
5771 // register is a parse error.
5772 if (Operand.isGPRAsmReg()) {
5773 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005774 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005775 }
5776
5777 return (RegNo == (unsigned)-1);
5778 }
5779
5780 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00005781 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00005782}
5783
Jack Carterb5cf5902013-04-17 00:18:04 +00005784bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00005785 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005786
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00005787 if (isParenExpr)
5788 return getParser().parseParenExprOfDepth(0, Res, S);
5789 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00005790}
5791
Alex Bradbury58eba092016-11-01 16:32:05 +00005792OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00005793MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005794 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005795 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00005796 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00005797 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00005798 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00005799 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00005800 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00005801 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00005802
Jack Carterb5cf5902013-04-17 00:18:04 +00005803 if (getLexer().getKind() == AsmToken::LParen) {
5804 Parser.Lex();
5805 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005806 }
5807
Jack Carterb5cf5902013-04-17 00:18:04 +00005808 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005809 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00005810 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005811
Jack Carterd0bd6422013-04-18 00:41:53 +00005812 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005813 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005814 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00005815 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005816 SMLoc E =
5817 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005818 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005819 return MatchOperand_Success;
5820 }
5821 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005822 SMLoc E =
5823 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00005824
Jack Carterd0bd6422013-04-18 00:41:53 +00005825 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005826 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00005827 auto Base = MipsOperand::createGPRReg(
5828 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00005829 Operands.push_back(
5830 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00005831 return MatchOperand_Success;
5832 }
Simon Dardis858915f2016-10-18 15:17:17 +00005833 MCBinaryExpr::Opcode Opcode;
5834 // GAS and LLVM treat comparison operators different. GAS will generate -1
5835 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
5836 // highly unlikely to be found in a memory offset expression, we don't
5837 // handle them.
5838 switch (Tok.getKind()) {
5839 case AsmToken::Plus:
5840 Opcode = MCBinaryExpr::Add;
5841 Parser.Lex();
5842 break;
5843 case AsmToken::Minus:
5844 Opcode = MCBinaryExpr::Sub;
5845 Parser.Lex();
5846 break;
5847 case AsmToken::Star:
5848 Opcode = MCBinaryExpr::Mul;
5849 Parser.Lex();
5850 break;
5851 case AsmToken::Pipe:
5852 Opcode = MCBinaryExpr::Or;
5853 Parser.Lex();
5854 break;
5855 case AsmToken::Amp:
5856 Opcode = MCBinaryExpr::And;
5857 Parser.Lex();
5858 break;
5859 case AsmToken::LessLess:
5860 Opcode = MCBinaryExpr::Shl;
5861 Parser.Lex();
5862 break;
5863 case AsmToken::GreaterGreater:
5864 Opcode = MCBinaryExpr::LShr;
5865 Parser.Lex();
5866 break;
5867 case AsmToken::Caret:
5868 Opcode = MCBinaryExpr::Xor;
5869 Parser.Lex();
5870 break;
5871 case AsmToken::Slash:
5872 Opcode = MCBinaryExpr::Div;
5873 Parser.Lex();
5874 break;
5875 case AsmToken::Percent:
5876 Opcode = MCBinaryExpr::Mod;
5877 Parser.Lex();
5878 break;
5879 default:
5880 Error(Parser.getTok().getLoc(), "'(' or expression expected");
5881 return MatchOperand_ParseFail;
5882 }
5883 const MCExpr * NextExpr;
5884 if (getParser().parseExpression(NextExpr))
5885 return MatchOperand_ParseFail;
5886 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005887 }
5888
Jack Carterd0bd6422013-04-18 00:41:53 +00005889 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00005890 }
5891
Toma Tabacu13964452014-09-04 13:23:44 +00005892 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005893 if (Res != MatchOperand_Success)
5894 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00005895
Vladimir Medic27c87ea2013-08-13 13:07:09 +00005896 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00005897 Error(Parser.getTok().getLoc(), "')' expected");
5898 return MatchOperand_ParseFail;
5899 }
5900
Jack Carter873c7242013-01-12 01:03:14 +00005901 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5902
Jack Carterd0bd6422013-04-18 00:41:53 +00005903 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005904
Craig Topper062a2ba2014-04-25 05:30:21 +00005905 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005906 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00005907
Jack Carterd0bd6422013-04-18 00:41:53 +00005908 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005909 std::unique_ptr<MipsOperand> op(
5910 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00005911 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00005912 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00005913 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00005914 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00005915 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
5916 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00005917 if (IdVal->evaluateAsAbsolute(Imm))
5918 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00005919 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00005920 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00005921 getContext());
5922 }
5923
David Blaikie960ea3f2014-06-08 16:18:35 +00005924 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005925 return MatchOperand_Success;
5926}
5927
David Blaikie960ea3f2014-06-08 16:18:35 +00005928bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005929 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00005930 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00005931 if (Sym) {
5932 SMLoc S = Parser.getTok().getLoc();
5933 const MCExpr *Expr;
5934 if (Sym->isVariable())
5935 Expr = Sym->getVariableValue();
5936 else
5937 return false;
5938 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00005939 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00005940 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00005941 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005942 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00005943 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00005944 if (ResTy == MatchOperand_Success) {
5945 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00005946 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00005947 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005948 llvm_unreachable("Should never ParseFail");
5949 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00005950 }
Jack Carterd76b2372013-03-21 21:44:16 +00005951 }
5952 }
5953 return false;
5954}
Jack Carterd0bd6422013-04-18 00:41:53 +00005955
Alex Bradbury58eba092016-11-01 16:32:05 +00005956OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00005957MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00005958 StringRef Identifier,
5959 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005960 int Index = matchCPURegisterName(Identifier);
5961 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005962 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005963 Index, Identifier, getContext().getRegisterInfo(), S,
5964 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005965 return MatchOperand_Success;
5966 }
5967
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005968 Index = matchHWRegsRegisterName(Identifier);
5969 if (Index != -1) {
5970 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005971 Index, Identifier, getContext().getRegisterInfo(), S,
5972 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00005973 return MatchOperand_Success;
5974 }
5975
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005976 Index = matchFPURegisterName(Identifier);
5977 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005978 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005979 Index, Identifier, getContext().getRegisterInfo(), S,
5980 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005981 return MatchOperand_Success;
5982 }
5983
5984 Index = matchFCCRegisterName(Identifier);
5985 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005986 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005987 Index, Identifier, getContext().getRegisterInfo(), S,
5988 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005989 return MatchOperand_Success;
5990 }
5991
5992 Index = matchACRegisterName(Identifier);
5993 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00005994 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00005995 Index, Identifier, getContext().getRegisterInfo(), S,
5996 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005997 return MatchOperand_Success;
5998 }
5999
6000 Index = matchMSA128RegisterName(Identifier);
6001 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006002 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006003 Index, Identifier, getContext().getRegisterInfo(), S,
6004 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006005 return MatchOperand_Success;
6006 }
6007
6008 Index = matchMSA128CtrlRegisterName(Identifier);
6009 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00006010 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006011 Index, Identifier, getContext().getRegisterInfo(), S,
6012 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006013 return MatchOperand_Success;
6014 }
6015
6016 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00006017}
6018
Alex Bradbury58eba092016-11-01 16:32:05 +00006019OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006020MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006021 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00006022 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006023
6024 if (Token.is(AsmToken::Identifier)) {
6025 DEBUG(dbgs() << ".. identifier\n");
6026 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00006027 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00006028 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00006029 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006030 } else if (Token.is(AsmToken::Integer)) {
6031 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00006032 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00006033 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
6034 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006035 return MatchOperand_Success;
6036 }
6037
6038 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
6039
6040 return MatchOperand_NoMatch;
6041}
6042
Alex Bradbury58eba092016-11-01 16:32:05 +00006043OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006044MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006045 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006046 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006047
6048 auto Token = Parser.getTok();
6049
6050 SMLoc S = Token.getLoc();
6051
6052 if (Token.isNot(AsmToken::Dollar)) {
6053 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
6054 if (Token.is(AsmToken::Identifier)) {
6055 if (searchSymbolAlias(Operands))
6056 return MatchOperand_Success;
6057 }
6058 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
6059 return MatchOperand_NoMatch;
6060 }
6061 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006062
Toma Tabacu13964452014-09-04 13:23:44 +00006063 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00006064 if (ResTy == MatchOperand_Success) {
6065 Parser.Lex(); // $
6066 Parser.Lex(); // identifier
6067 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006068 return ResTy;
6069}
6070
Alex Bradbury58eba092016-11-01 16:32:05 +00006071OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00006072MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006073 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00006074 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006075
6076 SMLoc S = getLexer().getLoc();
6077
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006078 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006079 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00006080 if (ResTy != MatchOperand_NoMatch)
6081 return ResTy;
6082
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00006083 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00006084 const MCExpr *Expr = nullptr;
6085 if (Parser.parseExpression(Expr)) {
6086 // We have no way of knowing if a symbol was consumed so we must ParseFail
6087 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006088 }
Daniel Sandersffd84362014-04-01 10:41:48 +00006089 Operands.push_back(
6090 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006091 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00006092}
6093
Alex Bradbury58eba092016-11-01 16:32:05 +00006094OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00006095MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006096 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00006097 const MCExpr *IdVal;
Simon Dardisa17a7b62017-10-10 13:34:45 +00006098 // If the first token is '$' we may have register operand. We have to reject
6099 // cases where it is not a register. Complicating the matter is that
6100 // register names are not reserved across all ABIs.
6101 // Peek past the dollar to see if it's a register name for this ABI.
Vladimir Medic2b953d02013-10-01 09:48:56 +00006102 SMLoc S = Parser.getTok().getLoc();
Simon Dardisa17a7b62017-10-10 13:34:45 +00006103 if (Parser.getTok().is(AsmToken::Dollar)) {
6104 return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
6105 ? MatchOperand_ParseFail
6106 : MatchOperand_NoMatch;
6107 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00006108 if (getParser().parseExpression(IdVal))
6109 return MatchOperand_ParseFail;
6110 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Simon Dardisa17a7b62017-10-10 13:34:45 +00006111 if (!MCE)
6112 return MatchOperand_NoMatch;
Vladimir Medic2b953d02013-10-01 09:48:56 +00006113 int64_t Val = MCE->getValue();
6114 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
6115 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00006116 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00006117 return MatchOperand_Success;
6118}
6119
Alex Bradbury58eba092016-11-01 16:32:05 +00006120OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006121MipsAsmParser::parseRegisterList(OperandVector &Operands) {
6122 MCAsmParser &Parser = getParser();
6123 SmallVector<unsigned, 10> Regs;
6124 unsigned RegNo;
6125 unsigned PrevReg = Mips::NoRegister;
6126 bool RegRange = false;
6127 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6128
6129 if (Parser.getTok().isNot(AsmToken::Dollar))
6130 return MatchOperand_ParseFail;
6131
6132 SMLoc S = Parser.getTok().getLoc();
6133 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
6134 SMLoc E = getLexer().getLoc();
6135 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
6136 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
6137 if (RegRange) {
6138 // Remove last register operand because registers from register range
6139 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006140 if ((isGP64bit() && RegNo == Mips::RA_64) ||
6141 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006142 Regs.push_back(RegNo);
6143 } else {
6144 unsigned TmpReg = PrevReg + 1;
6145 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006146 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
6147 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
6148 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006149 Error(E, "invalid register operand");
6150 return MatchOperand_ParseFail;
6151 }
6152
6153 PrevReg = TmpReg;
6154 Regs.push_back(TmpReg++);
6155 }
6156 }
6157
6158 RegRange = false;
6159 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006160 if ((PrevReg == Mips::NoRegister) &&
6161 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
6162 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006163 Error(E, "$16 or $31 expected");
6164 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006165 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
6166 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
6167 !isGP64bit()) ||
6168 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
6169 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
6170 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006171 Error(E, "invalid register operand");
6172 return MatchOperand_ParseFail;
6173 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00006174 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
6175 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
6176 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00006177 Error(E, "consecutive register numbers expected");
6178 return MatchOperand_ParseFail;
6179 }
6180
6181 Regs.push_back(RegNo);
6182 }
6183
6184 if (Parser.getTok().is(AsmToken::Minus))
6185 RegRange = true;
6186
6187 if (!Parser.getTok().isNot(AsmToken::Minus) &&
6188 !Parser.getTok().isNot(AsmToken::Comma)) {
6189 Error(E, "',' or '-' expected");
6190 return MatchOperand_ParseFail;
6191 }
6192
6193 Lex(); // Consume comma or minus
6194 if (Parser.getTok().isNot(AsmToken::Dollar))
6195 break;
6196
6197 PrevReg = RegNo;
6198 }
6199
6200 SMLoc E = Parser.getTok().getLoc();
6201 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6202 parseMemOperand(Operands);
6203 return MatchOperand_Success;
6204}
6205
Alex Bradbury58eba092016-11-01 16:32:05 +00006206OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006207MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
6208 MCAsmParser &Parser = getParser();
6209
6210 SMLoc S = Parser.getTok().getLoc();
6211 if (parseAnyRegister(Operands) != MatchOperand_Success)
6212 return MatchOperand_ParseFail;
6213
6214 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00006215 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00006216
Benjamin Kramer2b68d152016-05-09 10:31:17 +00006217 Operands.pop_back();
6218 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00006219 return MatchOperand_Success;
6220}
6221
Alex Bradbury58eba092016-11-01 16:32:05 +00006222OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00006223MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
6224 MCAsmParser &Parser = getParser();
6225 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
6226 SmallVector<unsigned, 10> Regs;
6227
6228 if (Parser.getTok().isNot(AsmToken::Dollar))
6229 return MatchOperand_ParseFail;
6230
6231 SMLoc S = Parser.getTok().getLoc();
6232
6233 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6234 return MatchOperand_ParseFail;
6235
6236 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6237 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6238 Regs.push_back(RegNo);
6239
6240 SMLoc E = Parser.getTok().getLoc();
6241 if (Parser.getTok().isNot(AsmToken::Comma)) {
6242 Error(E, "',' expected");
6243 return MatchOperand_ParseFail;
6244 }
6245
6246 // Remove comma.
6247 Parser.Lex();
6248
6249 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
6250 return MatchOperand_ParseFail;
6251
6252 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
6253 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
6254 Regs.push_back(RegNo);
6255
6256 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
6257
6258 return MatchOperand_Success;
6259}
6260
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006261/// Sometimes (i.e. load/stores) the operand may be followed immediately by
6262/// either this.
6263/// ::= '(', register, ')'
6264/// handle it before we iterate so we don't get tripped up by the lack of
6265/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006266bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006267 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006268 if (getLexer().is(AsmToken::LParen)) {
6269 Operands.push_back(
6270 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
6271 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006272 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006273 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006274 return Error(Loc, "unexpected token in argument list");
6275 }
6276 if (Parser.getTok().isNot(AsmToken::RParen)) {
6277 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006278 return Error(Loc, "unexpected token, expected ')'");
6279 }
6280 Operands.push_back(
6281 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
6282 Parser.Lex();
6283 }
6284 return false;
6285}
6286
6287/// Sometimes (i.e. in MSA) the operand may be followed immediately by
6288/// either one of these.
6289/// ::= '[', register, ']'
6290/// ::= '[', integer, ']'
6291/// handle it before we iterate so we don't get tripped up by the lack of
6292/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00006293bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00006294 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006295 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006296 if (getLexer().is(AsmToken::LBrac)) {
6297 Operands.push_back(
6298 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
6299 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00006300 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006301 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006302 return Error(Loc, "unexpected token in argument list");
6303 }
6304 if (Parser.getTok().isNot(AsmToken::RBrac)) {
6305 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006306 return Error(Loc, "unexpected token, expected ']'");
6307 }
6308 Operands.push_back(
6309 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
6310 Parser.Lex();
6311 }
6312 return false;
6313}
6314
David Blaikie960ea3f2014-06-08 16:18:35 +00006315bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
6316 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006317 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006318 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006319
6320 // We have reached first instruction, module directive are now forbidden.
6321 getTargetStreamer().forbidModuleDirective();
6322
Vladimir Medic74593e62013-07-17 15:00:42 +00006323 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00006324 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006325 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00006326 }
Vladimir Medic64828a12013-07-16 10:07:14 +00006327 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006328 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00006329
6330 // Read the remaining operands.
6331 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6332 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006333 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006334 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006335 return Error(Loc, "unexpected token in argument list");
6336 }
Toma Tabacu13964452014-09-04 13:23:44 +00006337 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006338 return true;
6339 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00006340
Jack Carterd0bd6422013-04-18 00:41:53 +00006341 while (getLexer().is(AsmToken::Comma)) {
6342 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00006343 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00006344 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00006345 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006346 return Error(Loc, "unexpected token in argument list");
6347 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006348 // Parse bracket and parenthesis suffixes before we iterate
6349 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00006350 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006351 return true;
6352 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00006353 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00006354 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00006355 }
6356 }
Jack Carterb4dbc172012-09-05 23:34:03 +00006357 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6358 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00006359 return Error(Loc, "unexpected token in argument list");
6360 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006361 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00006362 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00006363}
6364
Nirav Dave996fc132016-05-05 14:15:46 +00006365// FIXME: Given that these have the same name, these should both be
6366// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006367bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00006368 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00006369 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00006370}
6371
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006372bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006373 return Error(Loc, ErrorMsg);
6374}
6375
Jack Carter0b744b32012-10-04 02:29:46 +00006376bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006377 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006378 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00006379
6380 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00006381 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00006382
6383 Parser.Lex(); // Eat "noat".
6384
Jack Carterd0bd6422013-04-18 00:41:53 +00006385 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006387 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006388 return false;
6389 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006390
6391 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006392 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006393 return false;
6394}
Jack Carterd0bd6422013-04-18 00:41:53 +00006395
Jack Carter0b744b32012-10-04 02:29:46 +00006396bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00006397 // Line can be: ".set at", which sets $at to $1
6398 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00006399 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00006400 Parser.Lex(); // Eat "at".
6401
Jack Carter0b744b32012-10-04 02:29:46 +00006402 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006403 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00006404 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00006405
6406 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00006407 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006408 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00006409 }
6410
6411 if (getLexer().isNot(AsmToken::Equal)) {
6412 reportParseError("unexpected token, expected equals sign");
6413 return false;
6414 }
6415 Parser.Lex(); // Eat "=".
6416
6417 if (getLexer().isNot(AsmToken::Dollar)) {
6418 if (getLexer().is(AsmToken::EndOfStatement)) {
6419 reportParseError("no register specified");
6420 return false;
6421 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00006422 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00006423 return false;
6424 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006425 }
6426 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00006427
Toma Tabacu16a74492015-02-13 10:30:57 +00006428 // Find out what "reg" is.
6429 unsigned AtRegNo;
6430 const AsmToken &Reg = Parser.getTok();
6431 if (Reg.is(AsmToken::Identifier)) {
6432 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
6433 } else if (Reg.is(AsmToken::Integer)) {
6434 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00006435 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00006436 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00006437 return false;
6438 }
Toma Tabacu16a74492015-02-13 10:30:57 +00006439
6440 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00006441 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00006442 reportParseError("invalid register");
6443 return false;
6444 }
6445 Parser.Lex(); // Eat "reg".
6446
6447 // If this is not the end of the statement, report an error.
6448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6449 reportParseError("unexpected token, expected end of statement");
6450 return false;
6451 }
6452
6453 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
6454
6455 Parser.Lex(); // Consume the EndOfStatement.
6456 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006457}
6458
6459bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006460 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006461 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006462 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006464 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006465 return false;
6466 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006467 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00006468 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006469 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006470 return false;
6471}
6472
6473bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006474 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00006475 Parser.Lex();
6476 // If this is not the end of the statement, report an error.
6477 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006478 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006479 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00006480 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006481 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00006482 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00006483 Parser.Lex(); // Consume the EndOfStatement.
6484 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00006485}
6486
6487bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006488 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006489 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006490 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006492 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006493 return false;
6494 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006495 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006496 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006497 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006498 return false;
6499}
6500
6501bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006502 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00006503 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00006504 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00006505 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006506 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00006507 return false;
6508 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006509 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00006510 reportParseError("`noreorder' must be set before `nomacro'");
6511 return false;
6512 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00006513 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00006514 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00006515 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00006516 return false;
6517}
Jack Carterd76b2372013-03-21 21:44:16 +00006518
Daniel Sanders44934432014-08-07 12:03:36 +00006519bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006520 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006521 Parser.Lex();
6522
6523 // If this is not the end of the statement, report an error.
6524 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006525 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006526
6527 setFeatureBits(Mips::FeatureMSA, "msa");
6528 getTargetStreamer().emitDirectiveSetMsa();
6529 return false;
6530}
6531
6532bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006533 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00006534 Parser.Lex();
6535
6536 // If this is not the end of the statement, report an error.
6537 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006538 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00006539
6540 clearFeatureBits(Mips::FeatureMSA, "msa");
6541 getTargetStreamer().emitDirectiveSetNoMsa();
6542 return false;
6543}
6544
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006545bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006546 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00006547 Parser.Lex(); // Eat "nodsp".
6548
6549 // If this is not the end of the statement, report an error.
6550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6551 reportParseError("unexpected token, expected end of statement");
6552 return false;
6553 }
6554
6555 clearFeatureBits(Mips::FeatureDSP, "dsp");
6556 getTargetStreamer().emitDirectiveSetNoDsp();
6557 return false;
6558}
6559
Toma Tabacucc2502d2014-11-04 17:18:07 +00006560bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006561 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006562 Parser.Lex(); // Eat "mips16".
6563
Jack Carter39536722014-01-22 23:08:42 +00006564 // If this is not the end of the statement, report an error.
6565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006566 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00006567 return false;
6568 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00006569
6570 setFeatureBits(Mips::FeatureMips16, "mips16");
6571 getTargetStreamer().emitDirectiveSetMips16();
6572 Parser.Lex(); // Consume the EndOfStatement.
6573 return false;
6574}
6575
6576bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006577 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00006578 Parser.Lex(); // Eat "nomips16".
6579
6580 // If this is not the end of the statement, report an error.
6581 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6582 reportParseError("unexpected token, expected end of statement");
6583 return false;
6584 }
6585
6586 clearFeatureBits(Mips::FeatureMips16, "mips16");
6587 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00006588 Parser.Lex(); // Consume the EndOfStatement.
6589 return false;
6590}
6591
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006592bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006593 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006594 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006595 // Line can be: .set fp=32
6596 // .set fp=xx
6597 // .set fp=64
6598 Parser.Lex(); // Eat fp token
6599 AsmToken Tok = Parser.getTok();
6600 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006601 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006602 return false;
6603 }
6604 Parser.Lex(); // Eat '=' token.
6605 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006606
6607 if (!parseFpABIValue(FpAbiVal, ".set"))
6608 return false;
6609
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006611 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006612 return false;
6613 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006614 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006615 Parser.Lex(); // Consume the EndOfStatement.
6616 return false;
6617}
6618
Toma Tabacu32c72aa2015-06-30 09:36:50 +00006619bool MipsAsmParser::parseSetOddSPRegDirective() {
6620 MCAsmParser &Parser = getParser();
6621
6622 Parser.Lex(); // Eat "oddspreg".
6623 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6624 reportParseError("unexpected token, expected end of statement");
6625 return false;
6626 }
6627
6628 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6629 getTargetStreamer().emitDirectiveSetOddSPReg();
6630 return false;
6631}
6632
6633bool MipsAsmParser::parseSetNoOddSPRegDirective() {
6634 MCAsmParser &Parser = getParser();
6635
6636 Parser.Lex(); // Eat "nooddspreg".
6637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6638 reportParseError("unexpected token, expected end of statement");
6639 return false;
6640 }
6641
6642 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
6643 getTargetStreamer().emitDirectiveSetNoOddSPReg();
6644 return false;
6645}
6646
Simon Dardis805f1e02017-07-11 21:28:36 +00006647bool MipsAsmParser::parseSetMtDirective() {
6648 MCAsmParser &Parser = getParser();
6649 Parser.Lex(); // Eat "mt".
6650
6651 // If this is not the end of the statement, report an error.
6652 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6653 reportParseError("unexpected token, expected end of statement");
6654 return false;
6655 }
6656
6657 setFeatureBits(Mips::FeatureMT, "mt");
6658 getTargetStreamer().emitDirectiveSetMt();
6659 Parser.Lex(); // Consume the EndOfStatement.
6660 return false;
6661}
6662
6663bool MipsAsmParser::parseSetNoMtDirective() {
6664 MCAsmParser &Parser = getParser();
6665 Parser.Lex(); // Eat "nomt".
6666
6667 // If this is not the end of the statement, report an error.
6668 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6669 reportParseError("unexpected token, expected end of statement");
6670 return false;
6671 }
6672
6673 clearFeatureBits(Mips::FeatureMT, "mt");
6674
6675 getTargetStreamer().emitDirectiveSetNoMt();
6676 Parser.Lex(); // Consume the EndOfStatement.
6677 return false;
6678}
6679
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006680bool MipsAsmParser::parseSetNoCRCDirective() {
6681 MCAsmParser &Parser = getParser();
6682 Parser.Lex(); // Eat "nocrc".
6683
6684 // If this is not the end of the statement, report an error.
6685 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6686 reportParseError("unexpected token, expected end of statement");
6687 return false;
6688 }
6689
6690 clearFeatureBits(Mips::FeatureCRC, "crc");
6691
6692 getTargetStreamer().emitDirectiveSetNoCRC();
6693 Parser.Lex(); // Consume the EndOfStatement.
6694 return false;
6695}
6696
Toma Tabacu9db22db2014-09-09 10:15:38 +00006697bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006698 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006699 SMLoc Loc = getLexer().getLoc();
6700
6701 Parser.Lex();
6702 if (getLexer().isNot(AsmToken::EndOfStatement))
6703 return reportParseError("unexpected token, expected end of statement");
6704
6705 // Always keep an element on the options "stack" to prevent the user
6706 // from changing the initial options. This is how we remember them.
6707 if (AssemblerOptions.size() == 2)
6708 return reportParseError(Loc, ".set pop with no .set push");
6709
Akira Hatanakab11ef082015-11-14 06:35:56 +00006710 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006711 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006712 setAvailableFeatures(
6713 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
6714 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00006715
6716 getTargetStreamer().emitDirectiveSetPop();
6717 return false;
6718}
6719
6720bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006721 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00006722 Parser.Lex();
6723 if (getLexer().isNot(AsmToken::EndOfStatement))
6724 return reportParseError("unexpected token, expected end of statement");
6725
6726 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00006727 AssemblerOptions.push_back(
Eugene Zelenkodde94e42017-01-30 23:21:32 +00006728 llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00006729
6730 getTargetStreamer().emitDirectiveSetPush();
6731 return false;
6732}
6733
Toma Tabacu29696502015-06-02 09:48:04 +00006734bool MipsAsmParser::parseSetSoftFloatDirective() {
6735 MCAsmParser &Parser = getParser();
6736 Parser.Lex();
6737 if (getLexer().isNot(AsmToken::EndOfStatement))
6738 return reportParseError("unexpected token, expected end of statement");
6739
6740 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6741 getTargetStreamer().emitDirectiveSetSoftFloat();
6742 return false;
6743}
6744
6745bool MipsAsmParser::parseSetHardFloatDirective() {
6746 MCAsmParser &Parser = getParser();
6747 Parser.Lex();
6748 if (getLexer().isNot(AsmToken::EndOfStatement))
6749 return reportParseError("unexpected token, expected end of statement");
6750
6751 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6752 getTargetStreamer().emitDirectiveSetHardFloat();
6753 return false;
6754}
6755
Jack Carterd76b2372013-03-21 21:44:16 +00006756bool MipsAsmParser::parseSetAssignment() {
6757 StringRef Name;
6758 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00006759 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00006760
6761 if (Parser.parseIdentifier(Name))
6762 reportParseError("expected identifier after .set");
6763
6764 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006765 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00006766 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00006767
Jack Carter3b2c96e2014-01-22 23:31:38 +00006768 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00006769 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00006770
Jim Grosbach6f482002015-05-18 18:43:14 +00006771 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00006772 Sym->setVariableValue(Value);
6773
6774 return false;
6775}
Jack Carterd0bd6422013-04-18 00:41:53 +00006776
Toma Tabacu26647792014-09-09 12:52:14 +00006777bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006778 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00006779 Parser.Lex();
6780 if (getLexer().isNot(AsmToken::EndOfStatement))
6781 return reportParseError("unexpected token, expected end of statement");
6782
6783 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00006784 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00006785 setAvailableFeatures(
6786 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
6787 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00006788 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
6789
6790 getTargetStreamer().emitDirectiveSetMips0();
6791 return false;
6792}
6793
Toma Tabacu85618b32014-08-19 14:22:52 +00006794bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006795 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00006796 Parser.Lex();
6797 if (getLexer().isNot(AsmToken::Equal))
6798 return reportParseError("unexpected token, expected equals sign");
6799
6800 Parser.Lex();
6801 StringRef Arch;
6802 if (Parser.parseIdentifier(Arch))
6803 return reportParseError("expected arch identifier");
6804
6805 StringRef ArchFeatureName =
6806 StringSwitch<StringRef>(Arch)
6807 .Case("mips1", "mips1")
6808 .Case("mips2", "mips2")
6809 .Case("mips3", "mips3")
6810 .Case("mips4", "mips4")
6811 .Case("mips5", "mips5")
6812 .Case("mips32", "mips32")
6813 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006814 .Case("mips32r3", "mips32r3")
6815 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006816 .Case("mips32r6", "mips32r6")
6817 .Case("mips64", "mips64")
6818 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00006819 .Case("mips64r3", "mips64r3")
6820 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00006821 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00006822 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00006823 .Case("r4000", "mips3") // This is an implementation of Mips3.
6824 .Default("");
6825
6826 if (ArchFeatureName.empty())
6827 return reportParseError("unsupported architecture");
6828
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00006829 if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
6830 return reportParseError("mips64r6 does not support microMIPS");
6831
Toma Tabacu85618b32014-08-19 14:22:52 +00006832 selectArch(ArchFeatureName);
6833 getTargetStreamer().emitDirectiveSetArch(Arch);
6834 return false;
6835}
6836
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006837bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006838 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006839 Parser.Lex();
6840 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006841 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006842
Matheus Almeida2852af82014-04-22 10:15:54 +00006843 switch (Feature) {
6844 default:
6845 llvm_unreachable("Unimplemented feature");
6846 case Mips::FeatureDSP:
6847 setFeatureBits(Mips::FeatureDSP, "dsp");
6848 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006849 break;
Petar Jovanovic65f10242017-10-05 17:40:32 +00006850 case Mips::FeatureDSPR2:
6851 setFeatureBits(Mips::FeatureDSPR2, "dspr2");
6852 getTargetStreamer().emitDirectiveSetDspr2();
6853 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006854 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00006855 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00006856 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006857 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006858 case Mips::FeatureMips1:
6859 selectArch("mips1");
6860 getTargetStreamer().emitDirectiveSetMips1();
6861 break;
6862 case Mips::FeatureMips2:
6863 selectArch("mips2");
6864 getTargetStreamer().emitDirectiveSetMips2();
6865 break;
6866 case Mips::FeatureMips3:
6867 selectArch("mips3");
6868 getTargetStreamer().emitDirectiveSetMips3();
6869 break;
6870 case Mips::FeatureMips4:
6871 selectArch("mips4");
6872 getTargetStreamer().emitDirectiveSetMips4();
6873 break;
6874 case Mips::FeatureMips5:
6875 selectArch("mips5");
6876 getTargetStreamer().emitDirectiveSetMips5();
6877 break;
6878 case Mips::FeatureMips32:
6879 selectArch("mips32");
6880 getTargetStreamer().emitDirectiveSetMips32();
6881 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006882 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006883 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006884 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006885 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006886 case Mips::FeatureMips32r3:
6887 selectArch("mips32r3");
6888 getTargetStreamer().emitDirectiveSetMips32R3();
6889 break;
6890 case Mips::FeatureMips32r5:
6891 selectArch("mips32r5");
6892 getTargetStreamer().emitDirectiveSetMips32R5();
6893 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006894 case Mips::FeatureMips32r6:
6895 selectArch("mips32r6");
6896 getTargetStreamer().emitDirectiveSetMips32R6();
6897 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006898 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006899 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00006900 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00006901 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00006902 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00006903 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00006904 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00006905 break;
Daniel Sanders17793142015-02-18 16:24:50 +00006906 case Mips::FeatureMips64r3:
6907 selectArch("mips64r3");
6908 getTargetStreamer().emitDirectiveSetMips64R3();
6909 break;
6910 case Mips::FeatureMips64r5:
6911 selectArch("mips64r5");
6912 getTargetStreamer().emitDirectiveSetMips64R5();
6913 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00006914 case Mips::FeatureMips64r6:
6915 selectArch("mips64r6");
6916 getTargetStreamer().emitDirectiveSetMips64R6();
6917 break;
Petar Jovanovic3408caf2018-03-14 14:13:31 +00006918 case Mips::FeatureCRC:
6919 setFeatureBits(Mips::FeatureCRC, "crc");
6920 getTargetStreamer().emitDirectiveSetCRC();
6921 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00006922 }
6923 return false;
6924}
6925
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006926bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006927 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006928 if (getLexer().isNot(AsmToken::Comma)) {
6929 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006930 return Error(Loc, ErrorStr);
6931 }
6932
Matheus Almeida2852af82014-04-22 10:15:54 +00006933 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006934 return true;
6935}
6936
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006937// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
6938// In this class, it is only used for .cprestore.
6939// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
6940// MipsTargetELFStreamer and MipsAsmParser.
6941bool MipsAsmParser::isPicAndNotNxxAbi() {
6942 return inPicMode() && !(isABI_N32() || isABI_N64());
6943}
6944
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006945bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00006946 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00006947 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006948
Toma Tabacudde4c462014-11-06 10:02:45 +00006949 if (inMips16Mode()) {
6950 reportParseError(".cpload is not supported in Mips16 mode");
6951 return false;
6952 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006953
David Blaikie960ea3f2014-06-08 16:18:35 +00006954 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00006955 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006956 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6957 reportParseError("expected register containing function address");
6958 return false;
6959 }
6960
David Blaikie960ea3f2014-06-08 16:18:35 +00006961 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
6962 if (!RegOpnd.isGPRAsmReg()) {
6963 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006964 return false;
6965 }
6966
Toma Tabacudde4c462014-11-06 10:02:45 +00006967 // If this is not the end of the statement, report an error.
6968 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6969 reportParseError("unexpected token, expected end of statement");
6970 return false;
6971 }
6972
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006973 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006974 return false;
6975}
6976
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006977bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
6978 MCAsmParser &Parser = getParser();
6979
6980 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
6981 // is used in non-PIC mode.
6982
6983 if (inMips16Mode()) {
6984 reportParseError(".cprestore is not supported in Mips16 mode");
6985 return false;
6986 }
6987
6988 // Get the stack offset value.
6989 const MCExpr *StackOffset;
6990 int64_t StackOffsetVal;
6991 if (Parser.parseExpression(StackOffset)) {
6992 reportParseError("expected stack offset value");
6993 return false;
6994 }
6995
6996 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
6997 reportParseError("stack offset is not an absolute expression");
6998 return false;
6999 }
7000
7001 if (StackOffsetVal < 0) {
7002 Warning(Loc, ".cprestore with negative stack offset has no effect");
7003 IsCpRestoreSet = false;
7004 } else {
7005 IsCpRestoreSet = true;
7006 CpRestoreOffset = StackOffsetVal;
7007 }
7008
7009 // If this is not the end of the statement, report an error.
7010 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7011 reportParseError("unexpected token, expected end of statement");
7012 return false;
7013 }
7014
Daniel Sandersdf8510d2016-05-11 12:48:19 +00007015 if (!getTargetStreamer().emitDirectiveCpRestore(
7016 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00007017 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007018 Parser.Lex(); // Consume the EndOfStatement.
7019 return false;
7020}
7021
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007022bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007023 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007024 unsigned FuncReg;
7025 unsigned Save;
7026 bool SaveIsReg = true;
7027
Matheus Almeida7e815762014-06-18 13:08:59 +00007028 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007029 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007030 if (ResTy == MatchOperand_NoMatch) {
7031 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00007032 return false;
7033 }
7034
7035 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7036 if (!FuncRegOpnd.isGPRAsmReg()) {
7037 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007038 return false;
7039 }
7040
7041 FuncReg = FuncRegOpnd.getGPR32Reg();
7042 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007043
Toma Tabacu65f10572014-09-16 15:00:52 +00007044 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007045 return true;
7046
Toma Tabacu13964452014-09-04 13:23:44 +00007047 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00007048 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00007049 const MCExpr *OffsetExpr;
7050 int64_t OffsetVal;
7051 SMLoc ExprLoc = getLexer().getLoc();
7052
7053 if (Parser.parseExpression(OffsetExpr) ||
7054 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
7055 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00007056 return false;
7057 }
Daniel Sanders5d796282015-09-21 09:26:55 +00007058
7059 Save = OffsetVal;
7060 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00007061 } else {
7062 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7063 if (!SaveOpnd.isGPRAsmReg()) {
7064 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00007065 return false;
7066 }
7067 Save = SaveOpnd.getGPR32Reg();
7068 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007069
Toma Tabacu65f10572014-09-16 15:00:52 +00007070 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007071 return true;
7072
Toma Tabacu8874eac2015-02-18 13:46:53 +00007073 const MCExpr *Expr;
7074 if (Parser.parseExpression(Expr)) {
7075 reportParseError("expected expression");
7076 return false;
7077 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007078
Toma Tabacu8874eac2015-02-18 13:46:53 +00007079 if (Expr->getKind() != MCExpr::SymbolRef) {
7080 reportParseError("expected symbol");
7081 return false;
7082 }
7083 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
7084
Daniel Sandersf173dda2015-09-22 10:50:09 +00007085 CpSaveLocation = Save;
7086 CpSaveLocationIsRegister = SaveIsReg;
7087
Toma Tabacu8874eac2015-02-18 13:46:53 +00007088 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
7089 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00007090 return false;
7091}
7092
Daniel Sandersf173dda2015-09-22 10:50:09 +00007093bool MipsAsmParser::parseDirectiveCPReturn() {
7094 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
7095 CpSaveLocationIsRegister);
7096 return false;
7097}
7098
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007099bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007100 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007101 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7102 const AsmToken &Tok = Parser.getTok();
7103
7104 if (Tok.getString() == "2008") {
7105 Parser.Lex();
7106 getTargetStreamer().emitDirectiveNaN2008();
7107 return false;
7108 } else if (Tok.getString() == "legacy") {
7109 Parser.Lex();
7110 getTargetStreamer().emitDirectiveNaNLegacy();
7111 return false;
7112 }
7113 }
7114 // If we don't recognize the option passed to the .nan
7115 // directive (e.g. no option or unknown option), emit an error.
7116 reportParseError("invalid option in .nan directive");
7117 return false;
7118}
7119
Jack Carter0b744b32012-10-04 02:29:46 +00007120bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007121 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00007122 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00007123 const AsmToken &Tok = Parser.getTok();
7124
7125 if (Tok.getString() == "noat") {
7126 return parseSetNoAtDirective();
7127 } else if (Tok.getString() == "at") {
7128 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00007129 } else if (Tok.getString() == "arch") {
7130 return parseSetArchDirective();
Simon Dardisac9c30c2017-02-01 18:50:24 +00007131 } else if (Tok.getString() == "bopt") {
7132 Warning(Tok.getLoc(), "'bopt' feature is unsupported");
7133 getParser().Lex();
7134 return false;
7135 } else if (Tok.getString() == "nobopt") {
7136 // We're already running in nobopt mode, so nothing to do.
7137 getParser().Lex();
7138 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007139 } else if (Tok.getString() == "fp") {
7140 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00007141 } else if (Tok.getString() == "oddspreg") {
7142 return parseSetOddSPRegDirective();
7143 } else if (Tok.getString() == "nooddspreg") {
7144 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00007145 } else if (Tok.getString() == "pop") {
7146 return parseSetPopDirective();
7147 } else if (Tok.getString() == "push") {
7148 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00007149 } else if (Tok.getString() == "reorder") {
7150 return parseSetReorderDirective();
7151 } else if (Tok.getString() == "noreorder") {
7152 return parseSetNoReorderDirective();
7153 } else if (Tok.getString() == "macro") {
7154 return parseSetMacroDirective();
7155 } else if (Tok.getString() == "nomacro") {
7156 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00007157 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00007158 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007159 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00007160 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00007161 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00007162 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00007163 getTargetStreamer().emitDirectiveSetNoMicroMips();
7164 Parser.eatToEndOfStatement();
7165 return false;
7166 } else if (Tok.getString() == "micromips") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007167 if (hasMips64r6()) {
7168 Error(Tok.getLoc(), ".set micromips directive is not supported with MIPS64R6");
7169 return false;
7170 }
Matheus Almeida2852af82014-04-22 10:15:54 +00007171 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00007172 } else if (Tok.getString() == "mips0") {
7173 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00007174 } else if (Tok.getString() == "mips1") {
7175 return parseSetFeature(Mips::FeatureMips1);
7176 } else if (Tok.getString() == "mips2") {
7177 return parseSetFeature(Mips::FeatureMips2);
7178 } else if (Tok.getString() == "mips3") {
7179 return parseSetFeature(Mips::FeatureMips3);
7180 } else if (Tok.getString() == "mips4") {
7181 return parseSetFeature(Mips::FeatureMips4);
7182 } else if (Tok.getString() == "mips5") {
7183 return parseSetFeature(Mips::FeatureMips5);
7184 } else if (Tok.getString() == "mips32") {
7185 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00007186 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007187 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007188 } else if (Tok.getString() == "mips32r3") {
7189 return parseSetFeature(Mips::FeatureMips32r3);
7190 } else if (Tok.getString() == "mips32r5") {
7191 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007192 } else if (Tok.getString() == "mips32r6") {
7193 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00007194 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007195 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00007196 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007197 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00007198 } else if (Tok.getString() == "mips64r3") {
7199 return parseSetFeature(Mips::FeatureMips64r3);
7200 } else if (Tok.getString() == "mips64r5") {
7201 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00007202 } else if (Tok.getString() == "mips64r6") {
Aleksandar Beserminjid6dada12017-12-11 11:21:40 +00007203 if (inMicroMipsMode()) {
7204 Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS");
7205 return false;
7206 }
Daniel Sandersf0df2212014-08-04 12:20:00 +00007207 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00007208 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00007209 return parseSetFeature(Mips::FeatureDSP);
Petar Jovanovic65f10242017-10-05 17:40:32 +00007210 } else if (Tok.getString() == "dspr2") {
7211 return parseSetFeature(Mips::FeatureDSPR2);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00007212 } else if (Tok.getString() == "nodsp") {
7213 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00007214 } else if (Tok.getString() == "msa") {
7215 return parseSetMsaDirective();
7216 } else if (Tok.getString() == "nomsa") {
7217 return parseSetNoMsaDirective();
Simon Dardis805f1e02017-07-11 21:28:36 +00007218 } else if (Tok.getString() == "mt") {
7219 return parseSetMtDirective();
7220 } else if (Tok.getString() == "nomt") {
7221 return parseSetNoMtDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00007222 } else if (Tok.getString() == "softfloat") {
7223 return parseSetSoftFloatDirective();
7224 } else if (Tok.getString() == "hardfloat") {
7225 return parseSetHardFloatDirective();
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007226 } else if (Tok.getString() == "crc") {
7227 return parseSetFeature(Mips::FeatureCRC);
7228 } else if (Tok.getString() == "nocrc") {
7229 return parseSetNoCRCDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00007230 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00007231 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00007232 parseSetAssignment();
7233 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00007234 }
Jack Carter07c818d2013-01-25 01:31:34 +00007235
Jack Carter0b744b32012-10-04 02:29:46 +00007236 return true;
7237}
7238
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007239/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00007240/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00007241bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007242 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007243 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Eugene Zelenkodde94e42017-01-30 23:21:32 +00007244 while (true) {
Jack Carter07c818d2013-01-25 01:31:34 +00007245 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00007246 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00007247 return true;
7248
7249 getParser().getStreamer().EmitValue(Value, Size);
7250
7251 if (getLexer().is(AsmToken::EndOfStatement))
7252 break;
7253
Jack Carter07c818d2013-01-25 01:31:34 +00007254 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00007255 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00007256 Parser.Lex();
7257 }
7258 }
7259
7260 Parser.Lex();
7261 return false;
7262}
7263
Vladimir Medic4c299852013-11-06 11:27:05 +00007264/// parseDirectiveGpWord
7265/// ::= .gpword local_sym
7266bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007267 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00007268 const MCExpr *Value;
7269 // EmitGPRel32Value requires an expression, so we are using base class
7270 // method to evaluate the expression.
7271 if (getParser().parseExpression(Value))
7272 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00007273 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00007274
Vladimir Medice10c1122013-11-13 13:18:04 +00007275 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00007276 return Error(getLexer().getLoc(),
7277 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00007278 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00007279 return false;
7280}
7281
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007282/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00007283/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007284bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007285 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007286 const MCExpr *Value;
7287 // EmitGPRel64Value requires an expression, so we are using base class
7288 // method to evaluate the expression.
7289 if (getParser().parseExpression(Value))
7290 return true;
7291 getParser().getStreamer().EmitGPRel64Value(Value);
7292
7293 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007294 return Error(getLexer().getLoc(),
7295 "unexpected token, expected end of statement");
7296 Parser.Lex(); // Eat EndOfStatement token.
7297 return false;
7298}
7299
7300/// parseDirectiveDtpRelWord
7301/// ::= .dtprelword tls_sym
7302bool MipsAsmParser::parseDirectiveDtpRelWord() {
7303 MCAsmParser &Parser = getParser();
7304 const MCExpr *Value;
7305 // EmitDTPRel32Value requires an expression, so we are using base class
7306 // method to evaluate the expression.
7307 if (getParser().parseExpression(Value))
7308 return true;
7309 getParser().getStreamer().EmitDTPRel32Value(Value);
7310
7311 if (getLexer().isNot(AsmToken::EndOfStatement))
7312 return Error(getLexer().getLoc(),
7313 "unexpected token, expected end of statement");
7314 Parser.Lex(); // Eat EndOfStatement token.
7315 return false;
7316}
7317
7318/// parseDirectiveDtpRelDWord
7319/// ::= .dtpreldword tls_sym
7320bool MipsAsmParser::parseDirectiveDtpRelDWord() {
7321 MCAsmParser &Parser = getParser();
7322 const MCExpr *Value;
7323 // EmitDTPRel64Value requires an expression, so we are using base class
7324 // method to evaluate the expression.
7325 if (getParser().parseExpression(Value))
7326 return true;
7327 getParser().getStreamer().EmitDTPRel64Value(Value);
7328
7329 if (getLexer().isNot(AsmToken::EndOfStatement))
7330 return Error(getLexer().getLoc(),
7331 "unexpected token, expected end of statement");
7332 Parser.Lex(); // Eat EndOfStatement token.
7333 return false;
7334}
7335
7336/// parseDirectiveTpRelWord
7337/// ::= .tprelword tls_sym
7338bool MipsAsmParser::parseDirectiveTpRelWord() {
7339 MCAsmParser &Parser = getParser();
7340 const MCExpr *Value;
7341 // EmitTPRel32Value requires an expression, so we are using base class
7342 // method to evaluate the expression.
7343 if (getParser().parseExpression(Value))
7344 return true;
7345 getParser().getStreamer().EmitTPRel32Value(Value);
7346
7347 if (getLexer().isNot(AsmToken::EndOfStatement))
7348 return Error(getLexer().getLoc(),
7349 "unexpected token, expected end of statement");
7350 Parser.Lex(); // Eat EndOfStatement token.
7351 return false;
7352}
7353
7354/// parseDirectiveTpRelDWord
7355/// ::= .tpreldword tls_sym
7356bool MipsAsmParser::parseDirectiveTpRelDWord() {
7357 MCAsmParser &Parser = getParser();
7358 const MCExpr *Value;
7359 // EmitTPRel64Value requires an expression, so we are using base class
7360 // method to evaluate the expression.
7361 if (getParser().parseExpression(Value))
7362 return true;
7363 getParser().getStreamer().EmitTPRel64Value(Value);
7364
7365 if (getLexer().isNot(AsmToken::EndOfStatement))
7366 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00007367 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00007368 Parser.Lex(); // Eat EndOfStatement token.
7369 return false;
7370}
7371
Jack Carter0cd3c192014-01-06 23:27:31 +00007372bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007373 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00007374 // Get the option token.
7375 AsmToken Tok = Parser.getTok();
7376 // At the moment only identifiers are supported.
7377 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007378 return Error(Parser.getTok().getLoc(),
7379 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00007380 }
7381
7382 StringRef Option = Tok.getIdentifier();
7383
7384 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007385 // MipsAsmParser needs to know if the current PIC mode changes.
7386 IsPicEnabled = false;
7387
Jack Carter0cd3c192014-01-06 23:27:31 +00007388 getTargetStreamer().emitDirectiveOptionPic0();
7389 Parser.Lex();
7390 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007391 return Error(Parser.getTok().getLoc(),
7392 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00007393 }
7394 return false;
7395 }
7396
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007397 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00007398 // MipsAsmParser needs to know if the current PIC mode changes.
7399 IsPicEnabled = true;
7400
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007401 getTargetStreamer().emitDirectiveOptionPic2();
7402 Parser.Lex();
7403 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007404 return Error(Parser.getTok().getLoc(),
7405 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00007406 }
7407 return false;
7408 }
7409
Jack Carter0cd3c192014-01-06 23:27:31 +00007410 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00007411 Warning(Parser.getTok().getLoc(),
7412 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00007413 Parser.eatToEndOfStatement();
7414 return false;
7415}
7416
Toma Tabacu9ca50962015-04-16 09:53:47 +00007417/// parseInsnDirective
7418/// ::= .insn
7419bool MipsAsmParser::parseInsnDirective() {
7420 // If this is not the end of the statement, report an error.
7421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7422 reportParseError("unexpected token, expected end of statement");
7423 return false;
7424 }
7425
7426 // The actual label marking happens in
7427 // MipsELFStreamer::createPendingLabelRelocs().
7428 getTargetStreamer().emitDirectiveInsn();
7429
7430 getParser().Lex(); // Eat EndOfStatement token.
7431 return false;
7432}
7433
Simon Dardis1c73fcc2017-06-22 10:41:51 +00007434/// parseRSectionDirective
7435/// ::= .rdata
7436bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
7437 // If this is not the end of the statement, report an error.
7438 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7439 reportParseError("unexpected token, expected end of statement");
7440 return false;
7441 }
7442
7443 MCSection *ELFSection = getContext().getELFSection(
7444 Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
7445 getParser().getStreamer().SwitchSection(ELFSection);
7446
7447 getParser().Lex(); // Eat EndOfStatement token.
7448 return false;
7449}
7450
Simon Atanasyanbe186202016-02-11 06:45:54 +00007451/// parseSSectionDirective
7452/// ::= .sbss
7453/// ::= .sdata
7454bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
7455 // If this is not the end of the statement, report an error.
7456 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7457 reportParseError("unexpected token, expected end of statement");
7458 return false;
7459 }
7460
7461 MCSection *ELFSection = getContext().getELFSection(
7462 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
7463 getParser().getStreamer().SwitchSection(ELFSection);
7464
7465 getParser().Lex(); // Eat EndOfStatement token.
7466 return false;
7467}
7468
Daniel Sanders7e527422014-07-10 13:38:23 +00007469/// parseDirectiveModule
7470/// ::= .module oddspreg
7471/// ::= .module nooddspreg
7472/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00007473/// ::= .module softfloat
7474/// ::= .module hardfloat
Simon Dardis805f1e02017-07-11 21:28:36 +00007475/// ::= .module mt
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007476/// ::= .module crc
7477/// ::= .module nocrc
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007478bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007479 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007480 MCAsmLexer &Lexer = getLexer();
7481 SMLoc L = Lexer.getLoc();
7482
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00007483 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007484 // TODO : get a better message.
7485 reportParseError(".module directive must appear before any code");
7486 return false;
7487 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007488
Toma Tabacuc405c822015-01-23 10:40:19 +00007489 StringRef Option;
7490 if (Parser.parseIdentifier(Option)) {
7491 reportParseError("expected .module option identifier");
7492 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007493 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007494
Toma Tabacuc405c822015-01-23 10:40:19 +00007495 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007496 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007497
Toma Tabacu3c499582015-06-25 10:56:57 +00007498 // Synchronize the abiflags information with the FeatureBits information we
7499 // changed above.
7500 getTargetStreamer().updateABIInfo(*this);
7501
7502 // If printing assembly, use the recently updated abiflags information.
7503 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7504 // emitted at the end).
7505 getTargetStreamer().emitDirectiveModuleOddSPReg();
7506
Toma Tabacuc405c822015-01-23 10:40:19 +00007507 // If this is not the end of the statement, report an error.
7508 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7509 reportParseError("unexpected token, expected end of statement");
7510 return false;
7511 }
7512
7513 return false; // parseDirectiveModule has finished successfully.
7514 } else if (Option == "nooddspreg") {
7515 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00007516 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00007517 }
7518
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007519 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00007520
Toma Tabacu3c499582015-06-25 10:56:57 +00007521 // Synchronize the abiflags information with the FeatureBits information we
7522 // changed above.
7523 getTargetStreamer().updateABIInfo(*this);
7524
7525 // If printing assembly, use the recently updated abiflags information.
7526 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7527 // emitted at the end).
7528 getTargetStreamer().emitDirectiveModuleOddSPReg();
7529
Toma Tabacuc405c822015-01-23 10:40:19 +00007530 // If this is not the end of the statement, report an error.
7531 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7532 reportParseError("unexpected token, expected end of statement");
7533 return false;
7534 }
7535
7536 return false; // parseDirectiveModule has finished successfully.
7537 } else if (Option == "fp") {
7538 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00007539 } else if (Option == "softfloat") {
7540 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7541
7542 // Synchronize the ABI Flags information with the FeatureBits information we
7543 // updated above.
7544 getTargetStreamer().updateABIInfo(*this);
7545
7546 // If printing assembly, use the recently updated ABI Flags information.
7547 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7548 // emitted later).
7549 getTargetStreamer().emitDirectiveModuleSoftFloat();
7550
7551 // If this is not the end of the statement, report an error.
7552 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7553 reportParseError("unexpected token, expected end of statement");
7554 return false;
7555 }
7556
7557 return false; // parseDirectiveModule has finished successfully.
7558 } else if (Option == "hardfloat") {
7559 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
7560
7561 // Synchronize the ABI Flags information with the FeatureBits information we
7562 // updated above.
7563 getTargetStreamer().updateABIInfo(*this);
7564
7565 // If printing assembly, use the recently updated ABI Flags information.
7566 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7567 // emitted later).
7568 getTargetStreamer().emitDirectiveModuleHardFloat();
7569
7570 // If this is not the end of the statement, report an error.
7571 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7572 reportParseError("unexpected token, expected end of statement");
7573 return false;
7574 }
7575
7576 return false; // parseDirectiveModule has finished successfully.
Simon Dardis805f1e02017-07-11 21:28:36 +00007577 } else if (Option == "mt") {
7578 setModuleFeatureBits(Mips::FeatureMT, "mt");
7579
7580 // Synchronize the ABI Flags information with the FeatureBits information we
7581 // updated above.
7582 getTargetStreamer().updateABIInfo(*this);
7583
Simon Dardisd9611922017-07-11 21:36:58 +00007584 // If printing assembly, use the recently updated ABI Flags information.
Simon Dardis805f1e02017-07-11 21:28:36 +00007585 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7586 // emitted later).
7587 getTargetStreamer().emitDirectiveModuleMT();
7588
7589 // If this is not the end of the statement, report an error.
7590 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7591 reportParseError("unexpected token, expected end of statement");
7592 return false;
7593 }
7594
7595 return false; // parseDirectiveModule has finished successfully.
Petar Jovanovic3408caf2018-03-14 14:13:31 +00007596 } else if (Option == "crc") {
7597 setModuleFeatureBits(Mips::FeatureCRC, "crc");
7598
7599 // Synchronize the ABI Flags information with the FeatureBits information we
7600 // updated above.
7601 getTargetStreamer().updateABIInfo(*this);
7602
7603 // If printing assembly, use the recently updated ABI Flags information.
7604 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7605 // emitted later).
7606 getTargetStreamer().emitDirectiveModuleCRC();
7607
7608 // If this is not the end of the statement, report an error.
7609 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7610 reportParseError("unexpected token, expected end of statement");
7611 return false;
7612 }
7613
7614 return false; // parseDirectiveModule has finished successfully.
7615 } else if (Option == "nocrc") {
7616 clearModuleFeatureBits(Mips::FeatureCRC, "crc");
7617
7618 // Synchronize the ABI Flags information with the FeatureBits information we
7619 // updated above.
7620 getTargetStreamer().updateABIInfo(*this);
7621
7622 // If printing assembly, use the recently updated ABI Flags information.
7623 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7624 // emitted later).
7625 getTargetStreamer().emitDirectiveModuleNoCRC();
7626
7627 // If this is not the end of the statement, report an error.
7628 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7629 reportParseError("unexpected token, expected end of statement");
7630 return false;
7631 }
7632
7633 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00007634 } else {
7635 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
7636 }
Daniel Sanders7e527422014-07-10 13:38:23 +00007637}
7638
7639/// parseDirectiveModuleFP
7640/// ::= =32
7641/// ::= =xx
7642/// ::= =64
7643bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00007644 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00007645 MCAsmLexer &Lexer = getLexer();
7646
7647 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007648 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007649 return false;
7650 }
7651 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007652
Daniel Sanders7e527422014-07-10 13:38:23 +00007653 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007654 if (!parseFpABIValue(FpABI, ".module"))
7655 return false;
7656
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007657 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00007658 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007659 return false;
7660 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007661
Toma Tabacua64e5402015-06-25 12:44:38 +00007662 // Synchronize the abiflags information with the FeatureBits information we
7663 // changed above.
7664 getTargetStreamer().updateABIInfo(*this);
7665
7666 // If printing assembly, use the recently updated abiflags information.
7667 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
7668 // emitted at the end).
7669 getTargetStreamer().emitDirectiveModuleFP();
7670
Daniel Sanders7e527422014-07-10 13:38:23 +00007671 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00007672 return false;
7673}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007674
Daniel Sanders7e527422014-07-10 13:38:23 +00007675bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007676 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00007677 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007678 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007679 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007680
7681 if (Lexer.is(AsmToken::Identifier)) {
7682 StringRef Value = Parser.getTok().getString();
7683 Parser.Lex();
7684
7685 if (Value != "xx") {
7686 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7687 return false;
7688 }
7689
7690 if (!isABI_O32()) {
7691 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
7692 return false;
7693 }
7694
Daniel Sanders7e527422014-07-10 13:38:23 +00007695 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007696 if (ModuleLevelOptions) {
7697 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7698 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7699 } else {
7700 setFeatureBits(Mips::FeatureFPXX, "fpxx");
7701 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7702 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007703 return true;
7704 }
7705
7706 if (Lexer.is(AsmToken::Integer)) {
7707 unsigned Value = Parser.getTok().getIntVal();
7708 Parser.Lex();
7709
7710 if (Value != 32 && Value != 64) {
7711 reportParseError("unsupported value, expected 'xx', '32' or '64'");
7712 return false;
7713 }
7714
7715 if (Value == 32) {
7716 if (!isABI_O32()) {
7717 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
7718 return false;
7719 }
7720
Daniel Sanders7e527422014-07-10 13:38:23 +00007721 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007722 if (ModuleLevelOptions) {
7723 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7724 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7725 } else {
7726 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7727 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
7728 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007729 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00007730 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00007731 if (ModuleLevelOptions) {
7732 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
7733 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
7734 } else {
7735 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
7736 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
7737 }
Toma Tabacua64e5402015-06-25 12:44:38 +00007738 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007739
Daniel Sanders7e527422014-07-10 13:38:23 +00007740 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00007741 }
7742
7743 return false;
7744}
7745
Jack Carter0b744b32012-10-04 02:29:46 +00007746bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00007747 // This returns false if this function recognizes the directive
7748 // regardless of whether it is successfully handles or reports an
7749 // error. Otherwise it returns true to give the generic parser a
7750 // chance at recognizing it.
7751
Rafael Espindola961d4692014-11-11 05:18:41 +00007752 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00007753 StringRef IDVal = DirectiveID.getString();
7754
Nirav Dave996fc132016-05-05 14:15:46 +00007755 if (IDVal == ".cpload") {
7756 parseDirectiveCpLoad(DirectiveID.getLoc());
7757 return false;
7758 }
7759 if (IDVal == ".cprestore") {
7760 parseDirectiveCpRestore(DirectiveID.getLoc());
7761 return false;
7762 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00007763 if (IDVal == ".dword") {
7764 parseDataDirective(8, DirectiveID.getLoc());
7765 return false;
7766 }
Jack Carterd0bd6422013-04-18 00:41:53 +00007767 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007768 StringRef SymbolName;
7769
7770 if (Parser.parseIdentifier(SymbolName)) {
7771 reportParseError("expected identifier after .ent");
7772 return false;
7773 }
7774
7775 // There's an undocumented extension that allows an integer to
7776 // follow the name of the procedure which AFAICS is ignored by GAS.
7777 // Example: .ent foo,2
7778 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7779 if (getLexer().isNot(AsmToken::Comma)) {
7780 // Even though we accept this undocumented extension for compatibility
7781 // reasons, the additional integer argument does not actually change
7782 // the behaviour of the '.ent' directive, so we would like to discourage
7783 // its use. We do this by not referring to the extended version in
7784 // error messages which are not directly related to its use.
7785 reportParseError("unexpected token, expected end of statement");
7786 return false;
7787 }
7788 Parser.Lex(); // Eat the comma.
7789 const MCExpr *DummyNumber;
7790 int64_t DummyNumberVal;
7791 // If the user was explicitly trying to use the extended version,
7792 // we still give helpful extension-related error messages.
7793 if (Parser.parseExpression(DummyNumber)) {
7794 reportParseError("expected number after comma");
7795 return false;
7796 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00007797 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007798 reportParseError("expected an absolute expression after comma");
7799 return false;
7800 }
7801 }
7802
7803 // If this is not the end of the statement, report an error.
7804 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7805 reportParseError("unexpected token, expected end of statement");
7806 return false;
7807 }
7808
Jim Grosbach6f482002015-05-18 18:43:14 +00007809 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007810
7811 getTargetStreamer().emitDirectiveEnt(*Sym);
7812 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007813 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007814 return false;
7815 }
7816
Jack Carter07c818d2013-01-25 01:31:34 +00007817 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007818 StringRef SymbolName;
7819
7820 if (Parser.parseIdentifier(SymbolName)) {
7821 reportParseError("expected identifier after .end");
7822 return false;
7823 }
7824
7825 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7826 reportParseError("unexpected token, expected end of statement");
7827 return false;
7828 }
7829
7830 if (CurrentFn == nullptr) {
7831 reportParseError(".end used without .ent");
7832 return false;
7833 }
7834
7835 if ((SymbolName != CurrentFn->getName())) {
7836 reportParseError(".end symbol does not match .ent symbol");
7837 return false;
7838 }
7839
7840 getTargetStreamer().emitDirectiveEnd(SymbolName);
7841 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007842 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007843 return false;
7844 }
7845
Jack Carter07c818d2013-01-25 01:31:34 +00007846 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007847 // .frame $stack_reg, frame_size_in_bytes, $return_reg
7848 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00007849 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007850 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7851 reportParseError("expected stack register");
7852 return false;
7853 }
7854
7855 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7856 if (!StackRegOpnd.isGPRAsmReg()) {
7857 reportParseError(StackRegOpnd.getStartLoc(),
7858 "expected general purpose register");
7859 return false;
7860 }
7861 unsigned StackReg = StackRegOpnd.getGPR32Reg();
7862
7863 if (Parser.getTok().is(AsmToken::Comma))
7864 Parser.Lex();
7865 else {
7866 reportParseError("unexpected token, expected comma");
7867 return false;
7868 }
7869
7870 // Parse the frame size.
7871 const MCExpr *FrameSize;
7872 int64_t FrameSizeVal;
7873
7874 if (Parser.parseExpression(FrameSize)) {
7875 reportParseError("expected frame size value");
7876 return false;
7877 }
7878
Jim Grosbach13760bd2015-05-30 01:25:56 +00007879 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007880 reportParseError("frame size not an absolute expression");
7881 return false;
7882 }
7883
7884 if (Parser.getTok().is(AsmToken::Comma))
7885 Parser.Lex();
7886 else {
7887 reportParseError("unexpected token, expected comma");
7888 return false;
7889 }
7890
7891 // Parse the return register.
7892 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00007893 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00007894 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
7895 reportParseError("expected return register");
7896 return false;
7897 }
7898
7899 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
7900 if (!ReturnRegOpnd.isGPRAsmReg()) {
7901 reportParseError(ReturnRegOpnd.getStartLoc(),
7902 "expected general purpose register");
7903 return false;
7904 }
7905
7906 // If this is not the end of the statement, report an error.
7907 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7908 reportParseError("unexpected token, expected end of statement");
7909 return false;
7910 }
7911
7912 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
7913 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00007914 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00007915 return false;
7916 }
7917
Jack Carter07c818d2013-01-25 01:31:34 +00007918 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00007919 parseDirectiveSet();
7920 return false;
Jack Carterbe332172012-09-07 00:48:02 +00007921 }
7922
Daniel Sandersd97a6342014-08-13 10:07:34 +00007923 if (IDVal == ".mask" || IDVal == ".fmask") {
7924 // .mask bitmask, frame_offset
7925 // bitmask: One bit for each register used.
7926 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
7927 // first register is expected to be saved.
7928 // Examples:
7929 // .mask 0x80000000, -4
7930 // .fmask 0x80000000, -4
7931 //
Jack Carterbe332172012-09-07 00:48:02 +00007932
Daniel Sandersd97a6342014-08-13 10:07:34 +00007933 // Parse the bitmask
7934 const MCExpr *BitMask;
7935 int64_t BitMaskVal;
7936
7937 if (Parser.parseExpression(BitMask)) {
7938 reportParseError("expected bitmask value");
7939 return false;
7940 }
7941
Jim Grosbach13760bd2015-05-30 01:25:56 +00007942 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007943 reportParseError("bitmask not an absolute expression");
7944 return false;
7945 }
7946
7947 if (Parser.getTok().is(AsmToken::Comma))
7948 Parser.Lex();
7949 else {
7950 reportParseError("unexpected token, expected comma");
7951 return false;
7952 }
7953
7954 // Parse the frame_offset
7955 const MCExpr *FrameOffset;
7956 int64_t FrameOffsetVal;
7957
7958 if (Parser.parseExpression(FrameOffset)) {
7959 reportParseError("expected frame offset value");
7960 return false;
7961 }
7962
Jim Grosbach13760bd2015-05-30 01:25:56 +00007963 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00007964 reportParseError("frame offset not an absolute expression");
7965 return false;
7966 }
7967
7968 // If this is not the end of the statement, report an error.
7969 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7970 reportParseError("unexpected token, expected end of statement");
7971 return false;
7972 }
7973
7974 if (IDVal == ".mask")
7975 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
7976 else
7977 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00007978 return false;
7979 }
7980
Matheus Almeida0051f2d2014-04-16 15:48:55 +00007981 if (IDVal == ".nan")
7982 return parseDirectiveNaN();
7983
Jack Carter07c818d2013-01-25 01:31:34 +00007984 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00007985 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00007986 return false;
7987 }
7988
Rafael Espindolab59fb732014-03-28 18:50:26 +00007989 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00007990 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00007991 return false;
7992 }
7993
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00007994 if (IDVal == ".dtprelword") {
7995 parseDirectiveDtpRelWord();
7996 return false;
7997 }
7998
7999 if (IDVal == ".dtpreldword") {
8000 parseDirectiveDtpRelDWord();
8001 return false;
8002 }
8003
8004 if (IDVal == ".tprelword") {
8005 parseDirectiveTpRelWord();
8006 return false;
8007 }
8008
8009 if (IDVal == ".tpreldword") {
8010 parseDirectiveTpRelDWord();
8011 return false;
8012 }
8013
Jack Carter07c818d2013-01-25 01:31:34 +00008014 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00008015 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00008016 return false;
8017 }
8018
Scott Egertond1aeb052016-02-15 16:11:51 +00008019 if (IDVal == ".hword") {
8020 parseDataDirective(2, DirectiveID.getLoc());
8021 return false;
8022 }
8023
Nirav Dave996fc132016-05-05 14:15:46 +00008024 if (IDVal == ".option") {
8025 parseDirectiveOption();
8026 return false;
8027 }
Jack Carter0cd3c192014-01-06 23:27:31 +00008028
8029 if (IDVal == ".abicalls") {
8030 getTargetStreamer().emitDirectiveAbiCalls();
8031 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00008032 Error(Parser.getTok().getLoc(),
8033 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00008034 }
8035 return false;
8036 }
8037
Nirav Dave996fc132016-05-05 14:15:46 +00008038 if (IDVal == ".cpsetup") {
8039 parseDirectiveCPSetup();
8040 return false;
8041 }
8042 if (IDVal == ".cpreturn") {
8043 parseDirectiveCPReturn();
8044 return false;
8045 }
8046 if (IDVal == ".module") {
8047 parseDirectiveModule();
8048 return false;
8049 }
8050 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
8051 parseInternalDirectiveReallowModule();
8052 return false;
8053 }
8054 if (IDVal == ".insn") {
8055 parseInsnDirective();
8056 return false;
8057 }
Simon Dardis1c73fcc2017-06-22 10:41:51 +00008058 if (IDVal == ".rdata") {
8059 parseRSectionDirective(".rodata");
8060 return false;
8061 }
Nirav Dave996fc132016-05-05 14:15:46 +00008062 if (IDVal == ".sbss") {
8063 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
8064 return false;
8065 }
8066 if (IDVal == ".sdata") {
8067 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
8068 return false;
8069 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00008070
Rafael Espindola870c4e92012-01-11 03:56:41 +00008071 return true;
8072}
8073
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00008074bool MipsAsmParser::parseInternalDirectiveReallowModule() {
8075 // If this is not the end of the statement, report an error.
8076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8077 reportParseError("unexpected token, expected end of statement");
8078 return false;
8079 }
8080
8081 getTargetStreamer().reallowModuleDirective();
8082
8083 getParser().Lex(); // Eat EndOfStatement token.
8084 return false;
8085}
8086
Rafael Espindola870c4e92012-01-11 03:56:41 +00008087extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00008088 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
8089 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
8090 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
8091 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00008092}
Jack Carterb4dbc172012-09-05 23:34:03 +00008093
8094#define GET_REGISTER_MATCHER
8095#define GET_MATCHER_IMPLEMENTATION
8096#include "MipsGenAsmMatcher.inc"
Craig Topper55bc6cb2017-02-08 02:54:12 +00008097
8098bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
8099 // Find the appropriate table for this asm variant.
8100 const MatchEntry *Start, *End;
8101 switch (VariantID) {
8102 default: llvm_unreachable("invalid variant!");
8103 case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
8104 }
8105 // Search the table.
8106 auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
8107 return MnemonicRange.first != MnemonicRange.second;
8108}